/*
 * Public token contract.
 *
 * This stylesheet is the single place where public appearance is decided. It
 * consumes only the custom properties published by AppCustomizationService and
 * contains no selector naming a template, so adding a template to
 * config/tww/theme_palettes.php is sufficient for it to render correctly.
 *
 * Load order: this file must be last among the public stylesheets so its
 * token-driven declarations win over the older literal colours that remain in
 * tww-public.css. Where an older rule already used !important, the matching
 * declaration here repeats it; those are marked individually.
 *
 * Contract:
 *   --tww-public-bg              page background
 *   --tww-public-shell           full-page background image or gradient
 *   --tww-public-surface         card and panel background
 *   --tww-public-surface-strong  raised or opaque surface
 *   --tww-public-section-alt     alternating band background
 *   --tww-public-text            body text
 *   --tww-public-heading         headings and emphasised text
 *   --tww-public-muted           secondary text
 *   --tww-public-border          all borders and dividers
 *   --tww-public-primary         action colour
 *   --tww-public-accent          secondary action colour
 *   --tww-public-on-accent       text placed on primary/accent fills
 *   --tww-public-nav             navigation bar background
 *   --tww-public-footer          footer background
 *   --tww-public-footer-text     footer text
 *   --tww-public-focus           focus ring colour
 *   --tww-public-grid-opacity    decorative grid strength, 0 disables it
 *   --tww-public-radius          card corner radius
 */

/* ------------------------------------------------------------------ *
 * Legacy variable aliases.
 * Older public rules read --tww-surface / --tww-border / --tww-ink.
 * Mapping them here keeps those rules correct under every template
 * instead of leaving them on their dark-only literal fallbacks.
 * ------------------------------------------------------------------ */
body.tww-public-body {
    --tww-surface: var(--tww-public-surface);
    --tww-border: var(--tww-public-border);
    --tww-ink: var(--tww-public-text);
    --tww-muted: var(--tww-public-muted);
    --tww-card: var(--tww-public-surface);
    --tww-radius: var(--tww-public-radius);

    background: var(--tww-public-bg);
    color: var(--tww-public-text);
}

/* ------------------------------------------------------------------ *
 * Page shell
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-shell {
    background: var(--tww-public-shell);
    color: var(--tww-public-text);
}

/* The decorative grid is a template decision, not a fixed dark-theme
   flourish. A template sets --tww-public-grid-opacity to 0 to remove it. */
body.tww-public-body .tww-shell::before {
    opacity: var(--tww-public-grid-opacity);
    filter: none;
}

/* The former vignette darkened every surface, including light templates,
   and fought the shell gradient. Depth is now the gradient's job alone. */
body.tww-public-body .tww-shell::after {
    display: none;
}

/* ------------------------------------------------------------------ *
 * Navigation
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-public-nav .tww-nav-inner {
    background: var(--tww-public-nav);
    border-color: var(--tww-public-border);
    box-shadow: 0 16px 48px rgba(2, 6, 23, .16);
}

body.tww-public-body .tww-brand-title {
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-brand-sub,
body.tww-public-body .tww-menu a,
body.tww-public-body .tww-nav-link {
    color: var(--tww-public-muted);
}

body.tww-public-body .tww-menu a:hover,
body.tww-public-body .tww-nav-link:hover {
    background: color-mix(in srgb, var(--tww-public-primary) 12%, transparent);
    color: var(--tww-public-heading);
}

/* The current page is marked with an underline rather than a filled pill: a
   pill competes with the primary action beside it, and an underline survives
   any template without needing a background that contrasts against the nav. */
body.tww-public-body .tww-menu a[aria-current="page"],
body.tww-public-body .tww-nav-link[aria-current="page"] {
    background: transparent;
    color: var(--tww-public-heading);
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 5px;
    text-decoration-color: var(--tww-public-primary);
}

/* ------------------------------------------------------------------ *
 * Actions
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-btn-primary {
    background: var(--tww-public-primary);
    color: var(--tww-public-on-accent);
    box-shadow: 0 12px 30px color-mix(in srgb, var(--tww-public-primary) 28%, transparent);
}

body.tww-public-body .tww-btn-primary:hover {
    background: color-mix(in srgb, var(--tww-public-primary) 88%, var(--tww-public-heading));
}

body.tww-public-body .tww-btn-soft {
    background: var(--tww-public-surface);
    border: 1px solid var(--tww-public-border);
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-btn-light {
    background: var(--tww-public-surface-strong);
    color: var(--tww-public-heading);
    box-shadow: 0 12px 28px rgba(2, 6, 23, .14);
}

body.tww-public-body .tww-btn-dark {
    background: var(--tww-public-heading);
    color: var(--tww-public-surface-strong);
}

/* A visible focus ring on every interactive public control. */
body.tww-public-body :where(a, button, input, select, textarea, summary):focus-visible {
    outline: 2px solid var(--tww-public-primary);
    outline-offset: 2px;
    border-radius: 6px;
    box-shadow: 0 0 0 4px var(--tww-public-focus);
}

/* ------------------------------------------------------------------ *
 * Hero
 *
 * The home hero previously carried a hard-coded dark gradient and a light
 * heading colour under !important, so a light template still rendered a dark
 * hero. These declarations repeat !important only to reach those properties.
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-home-hero {
    background: var(--tww-public-shell) !important;
    color: var(--tww-public-text);
}

body.tww-public-body .tww-hero h1,
body.tww-public-body .tww-home-hero h1,
body.tww-public-body .tww-section-title,
body.tww-public-body .tww-public-page-header h1 {
    color: var(--tww-public-heading) !important;
}

/* The accented half of the hero headline.
 *
 * It is deliberately NOT gradient-clipped text here. tww-product-design-system.css
 * renders it solid with `-webkit-text-fill-color: currentColor !important`, and
 * setting `color: transparent` alongside that made currentColor transparent, so
 * the words vanished while still occupying the line and still being selectable.
 *
 * The design system already reads --tww-ds-primary, which is bridged to the
 * template primary further down, so the accent takes the template colour with
 * no override needed. Do not reintroduce background-clip here. */
body.tww-public-body .tww-gradient-text {
    color: var(--tww-public-primary);
}

body.tww-public-body .tww-lead,
body.tww-public-body .tww-section-copy,
body.tww-public-body .tww-public-page-header p {
    color: var(--tww-public-muted) !important;
}

body.tww-public-body .tww-kicker {
    background: var(--tww-public-surface);
    border-color: var(--tww-public-border);
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-metric,
body.tww-public-body .tww-panel,
body.tww-public-body .tww-stack-card,
body.tww-public-body .tww-auth-card,
body.tww-public-body .tww-form-shell {
    background: var(--tww-public-surface);
    border-color: var(--tww-public-border);
    color: var(--tww-public-text);
    backdrop-filter: none;
}

body.tww-public-body .tww-metric strong,
body.tww-public-body .tww-stack-card strong {
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-metric span,
body.tww-public-body .tww-stack-card span,
body.tww-public-body .tww-stack-card small,
body.tww-public-body .tww-smallcaps {
    color: var(--tww-public-muted);
}

body.tww-public-body .tww-icon {
    background: color-mix(in srgb, var(--tww-public-accent) 16%, transparent);
    color: var(--tww-public-accent);
}

/* ------------------------------------------------------------------ *
 * Sections and cards
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-section-light {
    background: var(--tww-public-section-alt);
    color: var(--tww-public-text);
}

body.tww-public-body .tww-card,
body.tww-public-body .tww-public-card,
body.tww-public-body .tww-portfolio-card,
body.tww-public-body .tww-portfolio-detail-card,
body.tww-public-body .tww-public-changelog-item,
body.tww-public-body .tww-blog-resources {
    background: var(--tww-public-surface-strong);
    border: 1px solid var(--tww-public-border);
    border-radius: var(--tww-public-radius);
    color: var(--tww-public-text);
    backdrop-filter: none;
    box-shadow: 0 14px 40px rgba(2, 6, 23, .10);
}

body.tww-public-body .tww-card-dark {
    background: var(--tww-public-surface);
    color: var(--tww-public-text);
}

body.tww-public-body :where(.tww-card, .tww-public-card, .tww-portfolio-body, .tww-portfolio-detail-card) h2,
body.tww-public-body :where(.tww-card, .tww-public-card, .tww-portfolio-body, .tww-portfolio-detail-card) h3,
body.tww-public-body .tww-rich-content :where(h1, h2, h3, h4),
body.tww-public-body .tww-empty-state strong,
body.tww-public-body .tww-spec-row strong {
    color: var(--tww-public-heading);
}

body.tww-public-body :where(.tww-card, .tww-public-card, .tww-portfolio-body, .tww-portfolio-detail-card) p,
body.tww-public-body .tww-card-dark p,
body.tww-public-body .tww-rich-content,
body.tww-public-body .tww-rich-copy,
body.tww-public-body .tww-public-meta-row,
body.tww-public-body .tww-stack-note,
body.tww-public-body .tww-empty-state,
body.tww-public-body .tww-public-empty-state,
body.tww-public-body .tww-spec-row span,
body.tww-public-body .tww-public-changelog-item p {
    color: var(--tww-public-muted);
}

/* Secondary text carried its contrast through opacity, which compounds against
   translucent surfaces. The muted token already encodes the intended contrast. */
body.tww-public-body .tww-public-meta-row,
body.tww-public-body .tww-stack-note {
    opacity: 1;
}

body.tww-public-body .tww-chip {
    background: var(--tww-public-section-alt);
    border-color: var(--tww-public-border);
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-empty-state,
body.tww-public-body .tww-public-empty-state {
    border-color: var(--tww-public-border);
}

body.tww-public-body .tww-spec-row {
    border-color: var(--tww-public-border);
}

body.tww-public-body .tww-blog-card-media {
    background: var(--tww-public-section-alt);
}

body.tww-public-body .tww-portfolio-visual {
    background: linear-gradient(135deg, var(--tww-public-primary), var(--tww-public-accent));
    color: var(--tww-public-on-accent);
}

/* ------------------------------------------------------------------ *
 * Filters and forms
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-public-filter-bar {
    background: var(--tww-public-surface-strong);
    border-color: var(--tww-public-border);
    color: var(--tww-public-text);
}

body.tww-public-body .tww-public-filter-bar label span,
body.tww-public-body .tww-form-shell label,
body.tww-public-body .tww-label {
    color: var(--tww-public-muted);
}

body.tww-public-body :where(.tww-public-filter-bar, .tww-form-shell) :where(input, select, textarea),
body.tww-public-body .tww-input {
    background: var(--tww-public-surface-strong);
    border: 1px solid var(--tww-public-border);
    color: var(--tww-public-text);
}

body.tww-public-body :where(.tww-public-filter-bar, .tww-form-shell) :where(input, select, textarea)::placeholder,
body.tww-public-body .tww-input::placeholder {
    color: var(--tww-public-muted);
    opacity: 1;
}

body.tww-public-body .tww-input:focus {
    border-color: var(--tww-public-primary);
    box-shadow: 0 0 0 4px var(--tww-public-focus);
}

body.tww-public-body .tww-form-shell button {
    background: var(--tww-public-primary) !important;
    color: var(--tww-public-on-accent) !important;
}

body.tww-public-body .tww-check {
    color: var(--tww-public-muted);
}

/* ------------------------------------------------------------------ *
 * Authentication surfaces
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-auth-readable {
    background: var(--tww-public-shell);
    color: var(--tww-public-text);
}

body.tww-public-body .tww-auth-copy h1 {
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-auth-copy p {
    color: var(--tww-public-muted);
}

body.tww-public-body .tww-login-card {
    background: var(--tww-public-surface);
    border-color: var(--tww-public-border);
    backdrop-filter: none;
}

body.tww-public-body .tww-login-inner {
    background: var(--tww-public-surface-strong);
    color: var(--tww-public-text);
}

body.tww-public-body .tww-login-inner h2 {
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-login-inner p,
body.tww-public-body .tww-register-box {
    color: var(--tww-public-muted);
}

body.tww-public-body .tww-register-box,
body.tww-public-body .tww-space-box {
    background: var(--tww-public-section-alt);
    border-color: var(--tww-public-border);
}

body.tww-public-body .tww-recovery,
body.tww-public-body .tww-register-box a {
    color: var(--tww-public-primary);
}

/* ------------------------------------------------------------------ *
 * Footer
 *
 * Footer tokens describe a solid block that is independent of the page
 * surface, so footer text and links resolve against the footer background.
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-footer {
    background: var(--tww-public-footer);
    color: var(--tww-public-footer-text);
    border-top-color: var(--tww-public-border);
}

body.tww-public-body .tww-footer a {
    color: var(--tww-public-footer-text);
}

body.tww-public-body .tww-footer a:hover {
    color: color-mix(in srgb, var(--tww-public-footer-text) 55%, #ffffff);
}

/* ------------------------------------------------------------------ *
 * Auto-layout
 *
 * Public grids size themselves from their content instead of fixed column
 * counts, so a section stays readable at every width without a breakpoint
 * for each template.
 * ------------------------------------------------------------------ */
body.tww-public-body .tww-grid,
body.tww-public-body .tww-portfolio-grid,
body.tww-public-body .tww-public-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
    gap: clamp(.85rem, 1.6vw, 1.35rem);
    align-items: start;
}

body.tww-public-body .tww-metrics {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 9.5rem), 1fr));
    gap: clamp(.6rem, 1.2vw, 1rem);
}

body.tww-public-body .tww-section-head {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
    gap: clamp(.75rem, 2vw, 1.75rem);
    align-items: end;
}

/* Wide content scrolls inside its own container rather than the page. */
body.tww-public-body :where(.tww-rich-content, .tww-public-card-body) :where(table, pre) {
    display: block;
    max-width: 100%;
    overflow-x: auto;
}

/* ------------------------------------------------------------------ *
 * Base token values.
 *
 * Published tokens land on :root and on html[data-theme="..."], both of
 * which outrank this element selector, so these values apply only when
 * the server could not publish a token set (for example a public page
 * rendered while the database is unavailable). Keeping them here means
 * the public site is never left with undefined colours.
 * ------------------------------------------------------------------ */
html {
    --tww-public-primary: #1d4ed8;
    --tww-public-accent: #0f766e;
    --tww-public-on-accent: #ffffff;
    --tww-public-bg: #f6f8fb;
    --tww-public-shell: linear-gradient(180deg, #ffffff 0%, #f6f8fb 42%, #eef2f8 100%);
    --tww-public-surface: #ffffff;
    --tww-public-surface-strong: #ffffff;
    --tww-public-section-alt: #eef2f8;
    --tww-public-text: #0f172a;
    --tww-public-heading: #0b1220;
    --tww-public-muted: #4a5768;
    --tww-public-border: #d5dde8;
    --tww-public-nav: rgba(255, 255, 255, .92);
    --tww-public-footer: #0f172a;
    --tww-public-footer-text: #cbd5e1;
    --tww-public-focus: rgba(29, 78, 216, .35);
    --tww-public-grid-opacity: 0;
    --tww-public-radius: 14px;
}

/* Native controls, scrollbars and form widgets follow the scheme the
   published token set was designed for. */
html[data-theme="light"] { color-scheme: light; }
html[data-theme="dark"] { color-scheme: dark; }

/* ------------------------------------------------------------------ *
 * Typography
 *
 * A template carries a body face and a separate display face, plus the
 * weight, tracking and casing its display voice depends on. Stacks are
 * platform fonts only: no font service is contacted and no build step is
 * required for a template to look the way it was designed.
 * ------------------------------------------------------------------ */
body.tww-public-body {
    --tww-font: var(--tww-public-font);

    font-family: var(--tww-public-font);
}

body.tww-public-body :where(input, select, textarea, button) {
    font-family: inherit;
}

body.tww-public-body :where(
    .tww-hero h1,
    .tww-home-hero h1,
    .tww-section-title,
    .tww-public-page-header h1,
    .tww-brand-title,
    .tww-portfolio-detail h1,
    .tww-auth-copy h1,
    .tww-login-inner h2
) {
    font-family: var(--tww-public-display-font);
    font-weight: var(--tww-public-display-weight);
    letter-spacing: var(--tww-public-display-tracking);
    text-transform: var(--tww-public-display-transform);
}

/* Card and section headings share the display voice at a calmer weight so a
   template reads as one typographic system rather than two. */
body.tww-public-body :where(.tww-card, .tww-public-card, .tww-portfolio-body, .tww-portfolio-detail-card) :where(h2, h3),
body.tww-public-body .tww-metric strong {
    font-family: var(--tww-public-display-font);
    letter-spacing: var(--tww-public-display-tracking);
    text-transform: var(--tww-public-display-transform);
}

/* Eyebrows and small caps keep their own steady treatment: they are wayfinding,
   not display, and must stay readable at small sizes in every template. */
body.tww-public-body :where(.tww-kicker, .tww-smallcaps, .tww-chip, .tww-spec-row span) {
    font-family: var(--tww-public-font);
    letter-spacing: .12em;
    text-transform: uppercase;
}

body.tww-public-body :where(.tww-lead, .tww-section-copy, .tww-rich-content, .tww-rich-copy) {
    font-family: var(--tww-public-font);
    letter-spacing: normal;
    text-transform: none;
}

/* Figures in specification rows and metrics align down a column. */
body.tww-public-body :where(.tww-metric strong, .tww-spec-row strong, .tww-public-meta-row, time) {
    font-variant-numeric: tabular-nums lining-nums;
}

/* ------------------------------------------------------------------ *
 * Page width
 *
 * Public pages previously sat inside a fixed 1180px column, so a wide
 * display was mostly empty margin. Width is now a template token: the
 * page uses the viewport, while prose is capped separately at a reading
 * measure so extra width becomes more columns, not longer lines.
 * ------------------------------------------------------------------ */
body.tww-public-body {
    --tww-public-gutter: clamp(1rem, 3vw, 2.75rem);
}

body.tww-public-body .tww-container,
body.tww-public-body .tww-nav-inner,
body.tww-public-body .tww-home-hero .tww-container,
body.tww-public-body .tww-public-main > .tww-container {
    width: min(100% - (var(--tww-public-gutter) * 2), var(--tww-public-container));
    max-width: none;
    margin-inline: auto;
}

body.tww-public-body .tww-reading-container {
    width: min(100% - (var(--tww-public-gutter) * 2), var(--tww-public-container));
    max-width: none;
}

/* Long-form text keeps a readable line length inside the wider page. */
body.tww-public-body :where(.tww-lead, .tww-section-copy, .tww-public-page-header p, .tww-rich-content p, .tww-rich-content li, .tww-rich-copy) {
    max-width: var(--tww-public-measure);
}

/* Card and portfolio grids spend the extra width on more columns. */
body.tww-public-body .tww-grid,
body.tww-public-body .tww-portfolio-grid,
body.tww-public-body .tww-public-card-grid {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 20.5rem), 1fr));
}

/* The hero keeps its two-part composition and grows with the page. */
body.tww-public-body .tww-hero-grid {
    gap: clamp(1.25rem, 3vw, 3rem);
}

@media (min-width: 1400px) {
    body.tww-public-body .tww-hero-grid {
        grid-template-columns: minmax(0, 1.15fr) minmax(22rem, .85fr);
    }
}

/* ------------------------------------------------------------------ *
 * Design-system bridge
 *
 * tww-product-design-system.css is the authoritative visual layer and
 * applies its declarations with !important. Its inputs are the console
 * token names, which are not published on public pages, so on the public
 * site it was falling back to its built-in light defaults and painting
 * admin colours over the selected template.
 *
 * Rather than compete with that layer, its inputs are re-pointed at the
 * public tokens here. Redefining them on the body element outranks the
 * :root defaults in that file, so the whole design system follows the
 * selected template and every component keeps the contrast the template
 * was measured for.
 * ------------------------------------------------------------------ */
body.tww-public-body {
    --tww-primary: var(--tww-public-primary);
    --tww-accent: var(--tww-public-accent);

    --tww-ds-primary: var(--tww-public-primary);
    --tww-ds-accent: var(--tww-public-accent);
    --tww-ds-page: var(--tww-public-bg);
    --tww-ds-surface: var(--tww-public-surface-strong);
    --tww-ds-content: var(--tww-public-section-alt);
    --tww-ds-control: var(--tww-public-surface-strong);
    --tww-ds-text: var(--tww-public-text);
    --tww-ds-text-primary: var(--tww-public-text);
    --tww-ds-text-secondary: var(--tww-public-muted);

    /* The default derives muted text by fading secondary text toward the
       surface, which drops it below AA on tinted backgrounds. The template
       already carries a muted colour measured against its own surfaces. */
    --tww-ds-muted: var(--tww-public-muted);

    --tww-ds-border: var(--tww-public-border);
    --tww-ds-border-strong: var(--tww-public-control-border);
    --tww-ds-focus: var(--tww-public-focus);

    --tww-ds-radius-sm: calc(var(--tww-public-radius) * 0.5);
    --tww-ds-radius-md: calc(var(--tww-public-radius) * 0.75);
    --tww-ds-radius-lg: var(--tww-public-radius);
    --tww-ds-radius-xl: var(--tww-public-radius);
}

/* Panel headings and copy follow the template like every other surface. */
body.tww-public-body .tww-panel-heading h2,
body.tww-public-body .tww-panel h2,
body.tww-public-body .tww-panel h3,
body.tww-public-body .tww-coverage-panel h2 {
    color: var(--tww-public-heading);
}

body.tww-public-body .tww-panel-copy,
body.tww-public-body .tww-panel p {
    color: var(--tww-public-muted);
}

/* The brand mark, auth logo and portfolio tile carry text on a filled accent,
   so they use the on-accent token rather than a fixed white. */
body.tww-public-body .tww-brand-mark,
body.tww-public-body .tww-login-logo {
    color: var(--tww-public-on-accent);
    background: linear-gradient(135deg, var(--tww-public-primary), var(--tww-public-accent));
}
