/* ==========================================================================
   GHOST TOWN FLY FISHING — DESIGN SYSTEM
   Single, build-free stylesheet shared by every page in /web.

   COLOUR SOURCE OF TRUTH
   ----------------------
   GOOGLE DRIVE PATH:
     Ghost Town Fly Fishing/01_Brand/Color/
       Ghost town fly fishing design color palette.zip
         -> "Ghost Town Phase 2F Palette.dc.html"   ("Shadow Pool & Paper")
   That artifact is authoritative. Every colour value in §1 below is copied
   from it verbatim. No colour here was invented, adjusted or optimised.
   Do not add a colour to this file that is not in that artifact.

   THE FOUR RULES (from the approved artifact, §02) — they govern this file:
     RULE 01  Blue is a SURFACE, not a small mark, on dark.
              On near-black, water blue appears as blocks, panels, tiles,
              rules and bars, with warm off-white type on top. Never as
              small blue text.
     RULE 02  #44677F is a CEILING, not a starting point.
              Nothing in this brand goes lighter than gt-water-lift-2.
     RULE 03  On dark, links and labels are PAPER.
              Warm off-white carries interactive text; the underline and
              hover carry state, with Ember on hover. Contrast is solved by
              neutrals, never by brightening the brand.
     RULE 04  ONE warm signal, used sparingly.
              Rust on paper, Ember on chrome. Never a second accent, never a
              gradient, never the logo.

   ARCHITECTURE
   ------------
   §1  Approved palette (raw)          §9   Links
   §2  Semantic tokens                 §10  Header / navigation
   §3  Surface contexts                §11  Hero
   §4  Typography / space / form       §12  Cards
   §5  Reset                           §13  Data & intelligence
   §6  Type scale                      §14  Tags, chips, status
   §7  Layout & widths                 §15  Forms
   §8  Buttons                         §16  Ask Ghost Town
                                       §17  Footer
                                       §18  Utilities, focus, motion, media

   Components read SURFACE-CONTEXT tokens (--gt-c-*), never raw palette
   values. Putting .gt-surface-chrome on an ancestor re-points the whole
   context, so one component definition works correctly on paper and on
   dark without a duplicate rule set.
   ========================================================================== */


/* ==========================================================================
   §1  APPROVED PALETTE — "Shadow Pool & Paper" (26 tokens, five families)
   Verbatim from the authoritative artifact. Never edit without a new
   approved artifact from Bobby.
   ========================================================================== */
:root {
  /* -- Foundation · surfaces · the ninety per cent -- */
  --gt-paper:            #FAF7F1;  /* Light page ground. Warm, pale, never beige. */
  --gt-paper-raised:     #FFFFFF;  /* Cards and inputs on paper. */
  --gt-paper-sunk:       #F2EEE5;  /* Alternating bands, quiet panels. */
  --gt-line:             #E3DDD1;  /* Hairlines and card borders on paper. */
  --gt-chrome:           #0E1113;  /* Dark page ground. Cool near-black. */
  --gt-chrome-line:      #2A2E31;  /* Hairlines on chrome. */

  /* -- Type · all reading text lives here -- */
  --gt-ink:              #14181B;  /* Primary text on paper. 16.7:1 */
  --gt-ink-muted:        #4A5257;  /* Body secondary, captions. 7.5:1 */
  --gt-ink-faint:        #8A8378;  /* Mono labels, metadata. 3.5:1 — large/mono only. */
  --gt-on-dark:          #FAF7F1;  /* All text on chrome and water, including links. */
  --gt-on-dark-muted:    #C9C4BB;  /* Secondary text and kickers on chrome. 10.9:1 */

  /* -- Water · the brand colour · surfaces and structure -- */
  --gt-water:            #22384A;  /* Primary. CTA fill, panels, tiles, rules, links on paper. */
  --gt-water-lift-1:     #2C4658;  /* Second surface step where two blues must separate. */
  --gt-water-lift-2:     #44677F;  /* CEILING. Rules, chips, bars, underlines on dark. Never lighter. */
  --gt-water-wash:       #E7ECEF;  /* Information panels and selected rows on paper. */
  --gt-water-line:       #C3CFD6;  /* Border for water washes on paper. */

  /* -- Warm signal · once or twice per screen -- */
  --gt-rust:             #B4552D;  /* Kickers, section numbers, hover on paper. 4.6:1 */
  --gt-ember:            #D07A46;  /* Kickers, hover, one highlighted series on chrome. 5.9:1 */
  --gt-rust-wash:        #F5E6DC;  /* Rare warm panel on paper. */

  /* -- Semantic · always paired with a glyph AND a word -- */
  --gt-good:             #2F5D3F;  /* Fishing well, open, confirmed — on paper. 7.6:1 */
  --gt-good-dark:        #7FA98B;  /* Same state on chrome. 7.2:1 */
  --gt-caution:          #8A6D1F;  /* High water, guide only, limited — on paper. 4.9:1 */
  --gt-caution-dark:     #D8B24A;  /* Same state on chrome. 9.4:1 */
  --gt-closed:           #9B2F2F;  /* Closed, failed, expired — on paper. 7.4:1 */
  --gt-closed-dark:      #E27C6A;  /* Same state on chrome. 6.6:1 */
  --gt-info:             #22384A;  /* Information is structural, not chromatic: it IS water. */

  /* Channel values, for the two places translucency is genuinely required
     (the sticky header backdrop and the photographic scrim). Every other
     surface in this file is an opaque token. Change these together with the
     hexes above if the palette is ever re-approved. */
  --gt-chrome-rgb:       14 17 19;
  --gt-ink-rgb:          20 24 27;
}


/* ==========================================================================
   §2  SEMANTIC TOKENS
   The names website code is allowed to use. Pages and components never
   reference §1 directly.
   ========================================================================== */
:root {
  /* -- Light surfaces -- */
  --gt-bg:                     var(--gt-paper);
  --gt-bg-secondary:           var(--gt-paper-sunk);
  --gt-surface:                var(--gt-paper-raised);
  --gt-surface-elevated:       var(--gt-paper-raised); /* separated by border + shadow, not a new colour */

  /* -- Dark surfaces -- */
  --gt-bg-dark:                var(--gt-chrome);
  --gt-surface-dark:           var(--gt-water);        /* RULE 01: panels on dark are water */
  --gt-surface-dark-elevated:  var(--gt-water-lift-1);

  /* -- Text -- */
  --gt-text:                   var(--gt-ink);
  --gt-text-secondary:         var(--gt-ink-muted);
  --gt-text-muted:             var(--gt-ink-faint);    /* mono/large only — 3.5:1 */
  --gt-text-on-dark:           var(--gt-on-dark);
  --gt-text-secondary-on-dark: var(--gt-on-dark-muted);

  /* -- Brand / action -- */
  --gt-accent:                 var(--gt-water);
  --gt-accent-hover:           var(--gt-water-lift-1);
  --gt-accent-secondary:       var(--gt-rust);
  --gt-accent-secondary-hover: var(--gt-ink);          /* neutral darkening; no second warm hue (RULE 04) */

  /* -- Links -- */
  --gt-link:                   var(--gt-water);
  --gt-link-hover:             var(--gt-rust);
  --gt-link-on-dark:           var(--gt-on-dark);      /* RULE 03 */
  --gt-link-on-dark-hover:     var(--gt-ember);

  /* -- Borders -- */
  --gt-border:                 var(--gt-line);
  --gt-border-strong:          var(--gt-ink-faint);    /* >=3:1 on all light surfaces — control edges */
  --gt-border-dark:            var(--gt-chrome-line);
  --gt-border-strong-dark:     var(--gt-water-lift-2); /* 3.15:1 on chrome — non-text only */

  /* -- Interaction -- */
  --gt-focus:                  var(--gt-water);
  --gt-focus-dark:             var(--gt-ember);

  /* -- Status -- */
  --gt-success:                var(--gt-good);
  --gt-warning:                var(--gt-caution);
  --gt-error:                  var(--gt-closed);
  --gt-success-on-dark:        var(--gt-good-dark);
  --gt-warning-on-dark:        var(--gt-caution-dark);
  --gt-error-on-dark:          var(--gt-closed-dark);

  /* -- On-colour text (all verified >=4.5:1 against their fill) -- */
  --gt-on-accent:              var(--gt-on-dark);  /* 11.3:1 on water */
  --gt-on-success:             var(--gt-on-dark);  /*  7.1:1 */
  --gt-on-warning:             var(--gt-on-dark);  /*  4.6:1 — ink would be 3.7:1 and fail */
  --gt-on-error:               var(--gt-on-dark);  /*  6.9:1 */

  /* -- Washes -- */
  --gt-wash-info:              var(--gt-water-wash);
  --gt-wash-info-border:       var(--gt-water-line);
  --gt-wash-warm:              var(--gt-rust-wash);

  /* -- Legacy aliases, kept so pre-existing inline styles keep resolving.
        New markup must not use these. Swept in §46 of the phase report. -- */
  --gt-border-soft:            var(--gt-border);
  --gt-text-dim:               var(--gt-text-secondary);
  --gt-muted:                  var(--gt-text-secondary);
}


/* ==========================================================================
   §3  SURFACE CONTEXTS
   A component asks the surface what colour it should be. Put
   .gt-surface-chrome (or --water / --paper) on any ancestor to re-point the
   whole subtree. This is what keeps one component definition correct on
   both light and dark ground.
   ========================================================================== */
:root,
.gt-surface-paper {
  --gt-c-bg:              var(--gt-bg);
  --gt-c-surface:         var(--gt-surface);
  --gt-c-surface-alt:     var(--gt-bg-secondary);
  --gt-c-text:            var(--gt-text);
  --gt-c-text-secondary:  var(--gt-text-secondary);
  --gt-c-text-muted:      var(--gt-text-muted);
  --gt-c-link:            var(--gt-link);
  --gt-c-link-hover:      var(--gt-link-hover);
  --gt-c-border:          var(--gt-border);
  --gt-c-border-strong:   var(--gt-border-strong);
  --gt-c-focus:           var(--gt-focus);
  --gt-c-accent:          var(--gt-accent);
  --gt-c-accent-hover:    var(--gt-accent-hover);
  --gt-c-on-accent:       var(--gt-on-accent);
  --gt-c-warm:            var(--gt-rust);
  --gt-c-success:         var(--gt-success);
  --gt-c-warning:         var(--gt-warning);
  --gt-c-error:           var(--gt-error);
}

.gt-surface-chrome {
  --gt-c-bg:              var(--gt-bg-dark);
  --gt-c-surface:         var(--gt-surface-dark);
  --gt-c-surface-alt:     var(--gt-surface-dark-elevated);
  --gt-c-text:            var(--gt-text-on-dark);
  --gt-c-text-secondary:  var(--gt-text-secondary-on-dark);
  --gt-c-text-muted:      var(--gt-text-secondary-on-dark);
  --gt-c-link:            var(--gt-link-on-dark);
  --gt-c-link-hover:      var(--gt-link-on-dark-hover);
  --gt-c-border:          var(--gt-border-dark);
  --gt-c-border-strong:   var(--gt-border-strong-dark);
  --gt-c-focus:           var(--gt-focus-dark);
  /* On chrome the primary action is a PAPER block with near-black type.
     Contrast is solved by neutrals, never by brightening the brand (RULE 03). */
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-chrome);
  --gt-c-warm:            var(--gt-ember);
  --gt-c-success:         var(--gt-success-on-dark);
  --gt-c-warning:         var(--gt-warning-on-dark);
  --gt-c-error:           var(--gt-error-on-dark);
}

/* A water panel sitting on chrome. Interactive text and status stay NEUTRAL
   here: Ember is only 3.8:1 on water and the dark status hues fall between
   4.2:1 and 6.0:1, so small coloured text is not permitted on this surface.
   Underline weight carries hover instead. */
.gt-surface-water {
  --gt-c-bg:              var(--gt-surface-dark);
  --gt-c-surface:         var(--gt-surface-dark-elevated);
  --gt-c-surface-alt:     var(--gt-surface-dark-elevated);
  --gt-c-text:            var(--gt-text-on-dark);
  --gt-c-text-secondary:  var(--gt-text-secondary-on-dark);
  --gt-c-text-muted:      var(--gt-text-secondary-on-dark);
  --gt-c-link:            var(--gt-link-on-dark);
  --gt-c-link-hover:      var(--gt-link-on-dark);
  --gt-c-border:          var(--gt-water-lift-2);
  --gt-c-border-strong:   var(--gt-on-dark-muted);
  --gt-c-focus:           var(--gt-paper);
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-water);
  --gt-c-warm:            var(--gt-on-dark);
  --gt-c-success:         var(--gt-text-on-dark);
  --gt-c-warning:         var(--gt-text-on-dark);
  --gt-c-error:           var(--gt-text-on-dark);
}

.gt-surface-paper,
.gt-surface-chrome,
.gt-surface-water { background: var(--gt-c-bg); color: var(--gt-c-text); }

/* Components sitting ON a dark band render their own surface in water, so the
   context has to step with them. Without this, .gt-intel-badge inherits
   chrome's Ember (3.78:1 on water) and status text inherits the dark status
   hues (4.2-6.0:1) - all of which fail as small text on that surface.
   Measured by rendered QA, not assumed. */
.gt-surface-chrome .gt-card,
.gt-surface-chrome .gt-intel-card,
.gt-surface-chrome .gt-panel,
.gt-surface-chrome .gt-stat,
.gt-surface-chrome .gt-stats,
.gt-surface-chrome .gt-alert,
.gt-section--panel .gt-card,
.gt-section--panel .gt-intel-card,
.gt-section--panel .gt-panel,
.gt-section--panel .gt-stat,
.gt-section--panel .gt-stats,
.gt-section--panel .gt-alert,
.gt-hero .gt-card,
.gt-hero .gt-intel-card,
.gt-hero .gt-panel {
  --gt-c-bg:              var(--gt-surface-dark);
  --gt-c-surface:         var(--gt-surface-dark-elevated);
  --gt-c-surface-alt:     var(--gt-surface-dark-elevated);
  --gt-c-text:            var(--gt-text-on-dark);
  --gt-c-text-secondary:  var(--gt-text-secondary-on-dark);
  --gt-c-text-muted:      var(--gt-text-secondary-on-dark);
  --gt-c-link:            var(--gt-link-on-dark);
  --gt-c-link-hover:      var(--gt-link-on-dark);
  --gt-c-border:          var(--gt-water-lift-2);
  --gt-c-border-strong:   var(--gt-on-dark-muted);
  --gt-c-focus:           var(--gt-paper);
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-water);
  --gt-c-warm:            var(--gt-text-secondary-on-dark);
  --gt-c-success:         var(--gt-text-on-dark);
  --gt-c-warning:         var(--gt-text-on-dark);
  --gt-c-error:           var(--gt-text-on-dark);
}
.gt-surface-chrome .gt-card,
.gt-surface-chrome .gt-intel-card,
.gt-surface-chrome .gt-panel,
.gt-section--panel .gt-card,
.gt-section--panel .gt-intel-card,
.gt-section--panel .gt-panel,
.gt-hero .gt-card,
.gt-hero .gt-intel-card,
.gt-hero .gt-panel { background: var(--gt-surface-dark); }


/* ==========================================================================
   §4  TYPOGRAPHY, SPACING, WIDTH, RADIUS, SHADOW
   Typography is taken from the approved brand materials, which are set in
   Newsreader + Public Sans + IBM Plex Mono. All three are open-source
   (SIL OFL) and served from Google Fonts with font-display: swap.
     Newsreader     — editorial serif. Display, headings, pull quotes.
     Public Sans    — neutral, highly legible UI/text sans. Body and controls.
     IBM Plex Mono  — field-notes register. Eyebrows, labels, data, metadata.
   ========================================================================== */
:root {
  --gt-font-display: "Newsreader", Georgia, "Times New Roman", serif;
  --gt-font-body:    "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --gt-font-mono:    "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* -- Type scale -- */
  --gt-fs-display:     clamp(2.5rem, 1.85rem + 2.9vw, 4rem);
  --gt-fs-h1:          clamp(2rem, 1.6rem + 1.9vw, 3rem);
  --gt-fs-h2:          clamp(1.55rem, 1.34rem + 0.95vw, 2.1rem);
  --gt-fs-h3:          clamp(1.2rem, 1.12rem + 0.38vw, 1.45rem);
  --gt-fs-h4:          1.125rem;
  --gt-fs-h5:          1rem;
  --gt-fs-h6:          0.9375rem;
  --gt-fs-body-lg:     1.125rem;
  --gt-fs-body:        1rem;
  --gt-fs-body-sm:     0.9375rem;
  --gt-fs-caption:     0.8125rem;
  --gt-fs-eyebrow:     0.6875rem;
  --gt-fs-nav:         0.9375rem;
  --gt-fs-button:      0.9375rem;
  --gt-fs-label:       0.75rem;
  --gt-fs-meta:        0.75rem;
  --gt-fs-stat:        clamp(1.75rem, 1.45rem + 1.4vw, 2.5rem);
  --gt-fs-stat-label:  0.6875rem;

  --gt-lh-tight:   1.08;
  --gt-lh-heading: 1.2;
  --gt-lh-body:    1.62;
  --gt-lh-ui:      1.4;

  --gt-ls-display: -0.02em;
  --gt-ls-heading: -0.012em;
  --gt-ls-mono:    0.14em;
  --gt-ls-label:   0.08em;

  /* -- Spacing scale (4px base) -- */
  --gt-space-1:  0.25rem;   /*  4 */
  --gt-space-2:  0.5rem;    /*  8 */
  --gt-space-3:  0.75rem;   /* 12 */
  --gt-space-4:  1rem;      /* 16 */
  --gt-space-5:  1.5rem;    /* 24 */
  --gt-space-6:  2rem;      /* 32 */
  --gt-space-8:  3rem;      /* 48 */
  --gt-space-10: 4rem;      /* 64 */
  --gt-space-12: 5rem;      /* 80 */
  --gt-space-16: 6.5rem;    /* 104 */
  --gt-space-20: 8rem;      /* 128 */
  /* Aliases kept for pre-existing inline styles in page markup. */
  --gt-space-7:  var(--gt-space-8);
  --gt-space-9:  var(--gt-space-12);

  /* -- Content widths (§13 of the phase brief) -- */
  --gt-w-wide:    1280px;   /* wide visual / data grids */
  --gt-w-content: 1120px;   /* normal content */
  --gt-w-read:    68ch;     /* editorial reading measure */
  --gt-w-narrow:  38rem;    /* forms, dialogs, single-column CTAs */
  --gt-max-width: var(--gt-w-content); /* legacy alias */

  /* -- Header height. Measured, not guessed, and now the single source of the
        number that three rules need: the overlay header's negative margin, the
        photographic hero's top padding, and the mobile nav panel's offset.
        The bar is 2 x --gt-space-3 of padding around its tallest control, so
        the value is fully determined by that control:
          <=900px  12 + 44 (nav toggle target) + 12 = 68
          >=901px  12 + 40 (Ask Ghost Town pill)+ 12 = 64
        The mobile panel previously hard-coded 65px against a 69px header and
        so opened 4px high, overlapping the bar. It reads this token now. -- */
  --gt-header-h: 68px;

  /* -- Radius: restrained on purpose. Ghost Town is not a SaaS dashboard. -- */
  --gt-radius-xs: 2px;   /* chips, tags, badges */
  --gt-radius-sm: 3px;   /* buttons, inputs */
  --gt-radius-md: 4px;   /* cards */
  --gt-radius-lg: 6px;   /* large feature surfaces, dialogs */

  /* -- Shadow: two levels, used sparingly. Identity comes from type,
        contrast, spacing and rules — not from floating cards. -- */
  --gt-shadow-sm: 0 1px 2px rgb(var(--gt-ink-rgb) / 0.06);
  --gt-shadow-md: 0 8px 28px rgb(var(--gt-ink-rgb) / 0.12);
  --gt-shadow: var(--gt-shadow-sm); /* legacy alias */
}

/* The desktop bar is shorter: the Ask Ghost Town pill (40px) replaces the
   44px nav toggle as the tallest thing in it. Same breakpoint the nav uses. */
@media (min-width: 901px) {
  :root { --gt-header-h: 64px; }
}


/* ==========================================================================
   §5  RESET
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--gt-bg);
  color: var(--gt-text);
  font-family: var(--gt-font-body);
  font-size: var(--gt-fs-body);
  line-height: var(--gt-lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { max-width: 100%; display: block; }
a { color: inherit; }
button, input, select, textarea { font-family: inherit; font-size: inherit; }
ul { list-style: none; margin: 0; padding: 0; }
h1, h2, h3, h4, h5, h6, p { margin: 0; }
hr { border: 0; border-top: 1px solid var(--gt-c-border, var(--gt-border)); margin: var(--gt-space-8) 0; }
::selection { background: var(--gt-water); color: var(--gt-on-dark); }


/* ==========================================================================
   §6  TYPE SCALE
   Hierarchy is carried by family, weight and colour as much as by size, so
   long informational pages stay scannable without every heading shouting.
   ========================================================================== */
h1, h2, h3, h4, h5, h6, .gt-display {
  font-family: var(--gt-font-display);
  font-weight: 500;
  line-height: var(--gt-lh-heading);
  letter-spacing: var(--gt-ls-heading);
  color: var(--gt-c-text, var(--gt-text));
  text-wrap: balance;
}
.gt-display { font-size: var(--gt-fs-display); line-height: var(--gt-lh-tight); letter-spacing: var(--gt-ls-display); }
h1 { font-size: var(--gt-fs-h1); line-height: var(--gt-lh-tight); letter-spacing: var(--gt-ls-display); }
h2 { font-size: var(--gt-fs-h2); }
h3 { font-size: var(--gt-fs-h3); font-weight: 600; }
h4 { font-size: var(--gt-fs-h4); font-weight: 600; }
h5 { font-size: var(--gt-fs-h5); font-weight: 600; }
/* h6 is the smallest structural heading: it steps into the mono register
   rather than shrinking the serif into illegibility. */
h6 {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-h6);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
}

/* Eyebrow / kicker — the one place the warm signal reliably appears. */
.gt-eyebrow {
  display: inline-block;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-eyebrow);
  font-weight: 500;
  letter-spacing: var(--gt-ls-mono);
  text-transform: uppercase;
  color: var(--gt-c-warm, var(--gt-rust));
  margin-bottom: var(--gt-space-3);
}

.gt-lede {
  font-size: var(--gt-fs-body-lg);
  line-height: 1.55;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  max-width: 62ch;
}
.gt-body-sm { font-size: var(--gt-fs-body-sm); }
.gt-caption { font-size: var(--gt-fs-caption); color: var(--gt-c-text-secondary, var(--gt-text-secondary)); }
.gt-muted   { color: var(--gt-c-text-secondary, var(--gt-text-secondary)); }

/* Metadata / citation line. Mono, letterspaced.
   ACCESSIBILITY REASSIGNMENT: the approved artifact clears gt-ink-faint
   (3.5:1 on paper) for "mono metadata at 10-11px letterspaced only". In
   practice this class carries readable sentences — source lines, gauge
   attributions, coordinates — so it is bound to text-secondary (7.5:1, AAA)
   instead. That is a SEMANTIC REASSIGNMENT within the approved palette, not
   a change to any approved colour value: gt-ink-faint is still shipped as a
   token and is still available for genuinely decorative marks. */
.gt-meta {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.06em;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-label {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}


/* ==========================================================================
   §7  LAYOUT & WIDTHS
   ========================================================================== */
.gt-wrap {
  width: 100%;
  max-width: var(--gt-w-content);
  margin: 0 auto;
  padding: 0 var(--gt-space-5);
}
.gt-wrap--wide   { max-width: var(--gt-w-wide); }
.gt-wrap--read   { max-width: calc(var(--gt-w-read) + (2 * var(--gt-space-5))); }
.gt-wrap--narrow { max-width: calc(var(--gt-w-narrow) + (2 * var(--gt-space-5))); }
@media (max-width: 640px) {
  .gt-wrap { padding: 0 var(--gt-space-4); }
}

.gt-section { padding: var(--gt-space-12) 0; }
.gt-section--tight { padding: var(--gt-space-8) 0; }
@media (max-width: 640px) {
  .gt-section { padding: var(--gt-space-10) 0; }
  .gt-section--tight { padding: var(--gt-space-6) 0; }
}

/* Alternating bands. --alt is the quiet paper band; --panel is a full dark
   band and carries the chrome context with it. */
.gt-section--alt {
  background: var(--gt-bg);
  border-top: 1px solid var(--gt-border);
  border-bottom: 1px solid var(--gt-border);
}
.gt-section--panel {
  background: var(--gt-bg-dark);
  color: var(--gt-text-on-dark);
  --gt-c-bg:              var(--gt-bg-dark);
  --gt-c-surface:         var(--gt-surface-dark);
  --gt-c-surface-alt:     var(--gt-surface-dark-elevated);
  --gt-c-text:            var(--gt-text-on-dark);
  --gt-c-text-secondary:  var(--gt-text-secondary-on-dark);
  --gt-c-text-muted:      var(--gt-text-secondary-on-dark);
  --gt-c-link:            var(--gt-link-on-dark);
  --gt-c-link-hover:      var(--gt-link-on-dark-hover);
  --gt-c-border:          var(--gt-border-dark);
  --gt-c-border-strong:   var(--gt-border-strong-dark);
  --gt-c-focus:           var(--gt-focus-dark);
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-chrome);
  --gt-c-warm:            var(--gt-ember);
  --gt-c-success:         var(--gt-success-on-dark);
  --gt-c-warning:         var(--gt-warning-on-dark);
  --gt-c-error:           var(--gt-error-on-dark);
}

.gt-section-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--gt-space-5);
  margin-bottom: var(--gt-space-8);
  padding-bottom: var(--gt-space-4);
  border-bottom: 1px solid var(--gt-c-border, var(--gt-border));
  flex-wrap: wrap;
}
.gt-section-head h2 { margin-top: 0; }
.gt-section-head .gt-lede { margin-top: var(--gt-space-3); }

/* The `min(Npx, 100%)` floor is deliberate. A bare `minmax(Npx, 1fr)` forces a
   track wider than the container once the viewport drops below N + container
   padding, which silently clips card content at 320px (the narrowest supported
   width) with no way to scroll to it, because `body { overflow-x: clip }`
   suppresses the scrollbar. `min()` lets the track collapse to the container
   instead. Found by rendered QA at 320px in Phase 2D. */
.gt-grid {
  display: grid;
  gap: var(--gt-space-5);
  grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
}
.gt-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
/* auto-FILL, not auto-fit: a section with a single card must occupy one column
   of three, not stretch across the row with an oversized media slot. Found by
   rendered QA on the Slovenia journal section. */
.gt-grid--3 { grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); }
.gt-grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); }


/* ==========================================================================
   §8  BUTTONS
   Primary CTA is deliberately scarce: at most one per section.
   Every variant is defined for default / hover / focus / active / disabled,
   and every one meets a 44px touch target.
   ========================================================================== */
.gt-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gt-space-2);
  min-height: 44px;
  padding: 11px 22px;
  border: 1px solid transparent;
  border-radius: var(--gt-radius-sm);
  font-family: var(--gt-font-body);
  font-size: var(--gt-fs-button);
  font-weight: 600;
  line-height: var(--gt-lh-ui);
  letter-spacing: 0.005em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.gt-btn--primary {
  background: var(--gt-c-accent, var(--gt-accent));
  color: var(--gt-c-on-accent, var(--gt-on-accent));
  border-color: var(--gt-c-accent, var(--gt-accent));
}
.gt-btn--primary:hover { background: var(--gt-c-accent-hover, var(--gt-accent-hover)); border-color: var(--gt-c-accent-hover, var(--gt-accent-hover)); }
.gt-btn--primary:active { background: var(--gt-c-accent, var(--gt-accent)); }

.gt-btn--secondary {
  background: transparent;
  color: var(--gt-c-text, var(--gt-text));
  border-color: var(--gt-c-border-strong, var(--gt-border-strong));
}
.gt-btn--secondary:hover {
  border-color: var(--gt-c-text, var(--gt-text));
  background: var(--gt-c-surface-alt, var(--gt-bg-secondary));
}

/* Tertiary / text button. */
.gt-btn--tertiary {
  background: transparent;
  border-color: transparent;
  color: var(--gt-c-link, var(--gt-link));
  padding-left: var(--gt-space-2);
  padding-right: var(--gt-space-2);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
}
.gt-btn--tertiary:hover { color: var(--gt-c-link-hover, var(--gt-link-hover)); text-decoration-thickness: 2px; }

.gt-btn--destructive {
  background: var(--gt-error);
  color: var(--gt-on-error);
  border-color: var(--gt-error);
}
.gt-btn--destructive:hover { background: var(--gt-ink); border-color: var(--gt-ink); }

.gt-btn[disabled],
.gt-btn[aria-disabled="true"],
.gt-btn--disabled {
  cursor: not-allowed;
  background: var(--gt-c-surface-alt, var(--gt-bg-secondary));
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  border-color: var(--gt-c-border, var(--gt-border));
  /* Disabled is signalled by border + label + the disabled attribute, not by
     colour alone, so it survives a colour-vision or high-contrast context. */
  text-decoration: none;
}
.gt-btn[disabled]:hover,
.gt-btn[aria-disabled="true"]:hover { background: var(--gt-c-surface-alt, var(--gt-bg-secondary)); }

.gt-btn--loading { cursor: progress; }
.gt-btn--loading::before {
  content: "";
  width: 13px; height: 13px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: gt-spin 0.7s linear infinite;
}
@keyframes gt-spin { to { transform: rotate(360deg); } }

.gt-btn--sm { min-height: 36px; padding: 7px 14px; font-size: var(--gt-fs-caption); }
.gt-btn--lg { min-height: 52px; padding: 14px 30px; font-size: var(--gt-fs-body); }
.gt-btn--block { width: 100%; }


/* ==========================================================================
   §9  LINKS
   Interactive text reads as interactive without any browser blue: on paper
   it is the brand's own deep water blue plus an underline; on chrome it is
   paper plus an underline, with Ember carrying hover (RULE 03).
   ========================================================================== */
/* :not(.gt-btn) matters: `.gt-prose a` outranks `.gt-btn--primary` on
   specificity, so without it a button placed inside prose gets the link
   colour painted over its own label - which on the primary button is water
   text on a water fill, i.e. invisible. Found by rendered QA on /about/ and
   /sources/. */
.gt-link,
.gt-prose a:not(.gt-btn),
.gt-rich a:not(.gt-btn) {
  color: var(--gt-c-link, var(--gt-link));
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color 0.12s ease, text-decoration-thickness 0.12s ease;
}
.gt-link:hover,
.gt-prose a:not(.gt-btn):hover,
.gt-rich a:not(.gt-btn):hover {
  color: var(--gt-c-link-hover, var(--gt-link-hover));
  text-decoration-thickness: 2px;
}

/* Standing arrow link used at section heads and card footers. */
.gt-link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--gt-font-body);
  font-size: var(--gt-fs-body-sm);
  font-weight: 600;
  color: var(--gt-c-link, var(--gt-link));
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
}
.gt-link-arrow:hover {
  color: var(--gt-c-link-hover, var(--gt-link-hover));
  border-bottom-color: currentColor;
}


/* ==========================================================================
   §10  HEADER / NAVIGATION
   The header is chrome, so the approved REVERSED wordmark master is the
   correct one on every page.
   ========================================================================== */
.gt-header {
  position: sticky;
  top: 0;
  z-index: 100;
  /* Opaque chrome, deliberately. At 0.94 alpha this bar composited against the
     paper body behind it and RENDERED as #1C1F20 - lighter than the hero's solid
     #0E1113, and a value that is not in the approved palette at all. That
     accidental step is what read as a darker block sitting under the header.
     Painting the approved token directly makes header, hero and the open mobile
     nav panel (already solid chrome) one surface. backdrop-filter went with it:
     it is a no-op behind an opaque fill. The --gt-chrome-rgb channel token stays
     - the photographic scrim and media caption still need it. */
  background: var(--gt-chrome);
  border-bottom: 1px solid var(--gt-chrome-line);
  color: var(--gt-text-on-dark);
  --gt-c-text:            var(--gt-text-on-dark);
  --gt-c-text-secondary:  var(--gt-text-secondary-on-dark);
  --gt-c-link:            var(--gt-link-on-dark);
  --gt-c-link-hover:      var(--gt-link-on-dark-hover);
  --gt-c-border:          var(--gt-border-dark);
  --gt-c-border-strong:   var(--gt-border-strong-dark);
  --gt-c-focus:           var(--gt-focus-dark);
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-chrome);
  --gt-c-surface-alt:     var(--gt-surface-dark);
  --gt-c-warm:            var(--gt-ember);
}

/* Header-into-hero continuity. Where the page opens on a chrome hero, header and
   hero are now the same approved surface and are meant to read as one dark
   composition, so the hairline between them is the only remaining boundary -
   and a full-width rule directly under the navigation is exactly what drew the
   eye away from the headline. It is suppressed there and kept everywhere else,
   where the header meets light content and still needs its edge (§8 allows a
   separator "if needed"; between two identical surfaces it is not needed).
   .gt-hero is used on the homepage only. */
@supports selector(:has(*)) {
  .gt-header:has(+ main .gt-hero) { border-bottom-color: transparent; }
}
.gt-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gt-space-4);
  /* Vertical padding only. The horizontal padding is deliberately left to .gt-wrap:
     the shorthand previously used here reset it to 0, which put the header contents
     flush against the viewport edge at =<1200px and left the approved wordmark with
     no clear space on its left. The wordmark specification requires 0.5 x cap height
     (4.01% of the mark's width) on all four sides, so the inherited wrap padding is
     required rather than cosmetic. This also aligns the header with body content. */
  padding-top: var(--gt-space-3);
  padding-bottom: var(--gt-space-3);
}
.gt-logo {
  display: flex;
  align-items: center;
  text-decoration: none;
  color: var(--gt-text-on-dark);
}
/* Approved Ghost Town primary wordmark (v1.0). The artwork IS the logo: it is never
   rebuilt as live text, never recoloured, and the reversed master is used as supplied
   rather than derived from the positive with a CSS filter. Width is set and height
   follows the 11.765:1 ratio of the reversed master, per the approved specification.
   Specification floor is 160px; preferred 160-200px mobile, 200-300px desktop.
   Clear space (0.5 x cap height = 4.01% of width) is satisfied by the existing header
   padding and flex gap, so no extra margin is applied here.
   RULE 04: the wordmark is never tinted with an accent colour. */
.gt-logo__wordmark {
  display: block;
  width: clamp(168px, 46vw, 200px);
  height: auto;
  flex-shrink: 0;
}
@media (min-width: 901px) {
  .gt-logo__wordmark { width: clamp(200px, 18vw, 252px); }
}
.gt-logo--footer .gt-logo__wordmark { width: clamp(168px, 38vw, 200px); }

.gt-nav { display: flex; align-items: center; gap: var(--gt-space-5); }
.gt-nav__links { display: flex; align-items: center; gap: var(--gt-space-5); }
.gt-nav__links a {
  display: inline-block;
  font-size: var(--gt-fs-nav);
  font-weight: 500;
  line-height: var(--gt-lh-ui);
  text-decoration: none;
  color: var(--gt-text-secondary-on-dark);
  padding: 8px 0;
  border-bottom: 2px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.gt-nav__links a:hover {
  color: var(--gt-text-on-dark);
  border-bottom-color: var(--gt-ember);
}
/* Active page is signalled by BOTH colour and a persistent rule, and carries
   aria-current in the markup — never colour alone. */
.gt-nav__links a[aria-current="page"] {
  color: var(--gt-text-on-dark);
  border-bottom-color: var(--gt-water-lift-2);
}
.gt-nav__ask {
  background: var(--gt-paper);
  color: var(--gt-chrome) !important;
  border-radius: var(--gt-radius-sm);
  padding: 9px 16px !important;
  border-bottom: none !important;
  font-weight: 600 !important;
  min-height: 40px;
  display: inline-flex !important;
  align-items: center;
}
.gt-nav__ask:hover { background: var(--gt-on-dark-muted); border-color: transparent !important; }

.gt-nav-toggle {
  display: none;
  min-width: 44px;
  min-height: 44px;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--gt-chrome-line);
  border-radius: var(--gt-radius-sm);
  color: var(--gt-text-on-dark);
  cursor: pointer;
}
.gt-nav-toggle:hover { border-color: var(--gt-water-lift-2); }

@media (max-width: 900px) {
  .gt-nav-toggle { display: inline-flex; }
  .gt-nav {
    position: fixed;
    inset: 0 0 0 auto;
    /* Was a hard-coded 65px against a 69px header, so the panel opened 4px high
       and covered the bottom of the bar. It reads the measured token now, plus
       whatever hairline that page's header carries — 1px normally, 0 under the
       overlay header, which has no border to clear (§10a). */
    top: calc(var(--gt-header-h) + var(--gt-header-hairline, 1px));
    width: min(320px, 84vw);
    height: calc(100vh - var(--gt-header-h) - var(--gt-header-hairline, 1px));
    background: var(--gt-chrome);
    border-left: 1px solid var(--gt-chrome-line);
    box-shadow: var(--gt-shadow-md);
    flex-direction: column;
    align-items: stretch;
    padding: var(--gt-space-5);
    transform: translateX(100%);
    transition: transform 0.22s ease;
    overflow-y: auto;
  }
  .gt-nav.is-open { transform: translateX(0); }
  .gt-nav__links {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--gt-space-2);
    width: 100%;
  }
  .gt-nav__links li { width: 100%; }
  .gt-nav__links a { width: 100%; padding: 12px 0; border-bottom: 1px solid var(--gt-chrome-line); }
  .gt-nav__ask { width: 100%; justify-content: center; margin-top: var(--gt-space-3); }
}


/* --------------------------------------------------------------------------
   §10a  OVERLAY HEADER  —  .gt-header--overlay

   The homepage opens on a photograph, and an opaque chrome bar above it drew a
   hard horizontal seam: solid dark, edge, picture. This modifier lets the
   photograph run to the top of the document and the header sit ON it, so the
   whole top of the page reads as one photographic composition.

   MECHANISM — no new element, no new colour, no layout guesswork.
     The header keeps position: sticky and its flow slot. It gives that slot
     back with a negative bottom margin of exactly --gt-header-h, so the hero
     slides up underneath it, and .gt-hero--photo pays the same number back as
     top padding so the copy still clears the navigation. The bar's height is
     pinned to the token rather than left to content, which makes the two
     numbers identical by construction — a computed-height drift would show as
     a chrome sliver above the photograph, i.e. the seam again.

     The darkness behind the wordmark and the links comes from a third,
     px-anchored layer on the hero's existing scrim (§11a), NOT from a fill on
     this element. A fill — at any alpha — is a rectangle, and a rectangle is
     what Bobby rejected.

   PROGRESSIVE ENHANCEMENT — why this is gated on .gt-js.
     A transparent header is only safe while a dark photograph is behind it.
     Scrolled past the hero it would sit on paper, and paper-on-paper links are
     invisible. Restoring the chrome ground at that point takes script, so the
     transparency is gated on the same class the head script sets: with no
     script the header stays the opaque sticky bar every other page uses, which
     is a working page, not a broken one. main.js adds .is-pinned.

   Base .gt-header is untouched, so every other page is byte-identical.
   -------------------------------------------------------------------------- */
.gt-js .gt-header--overlay {
  background: transparent;
  border-bottom: 0;
  /* Inherited by the mobile nav panel, which offsets itself by bar + hairline. */
  --gt-header-hairline: 0px;
  margin-bottom: calc(-1 * var(--gt-header-h));
  /* A colour fade, not motion — nothing here animates position or size. */
  transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
.gt-js .gt-header--overlay .gt-header__bar {
  height: var(--gt-header-h);
  padding-top: 0;
  padding-bottom: 0;
}

/* Once the photograph has scrolled away the bar takes its ground back. The
   hairline returns as a box-shadow rather than a border so restoring it costs
   no layout — a 1px border here would nudge the whole page on every pin. */
.gt-js .gt-header--overlay.is-pinned {
  background: var(--gt-chrome);
  box-shadow: 0 1px 0 var(--gt-chrome-line);
}

/* Nav links over a photograph, by the same argument §11a makes for the hero's
   secondary copy: --gt-on-dark-muted (#C9C4BB) is a 10.9:1 tone on flat chrome
   but only ~3.6-4.2:1 over a picture, and rescuing it would mean crushing the
   image. Promote to paper and let size and weight carry the hierarchy, per
   palette RULE 03. Held through .is-pinned too, so pinning changes the ground
   and nothing else. RULE 04 is intact: Ember is still the hover signal. */
.gt-js .gt-header--overlay .gt-nav__links a {
  color: var(--gt-text-on-dark);
  text-shadow: 0 1px 3px rgb(var(--gt-chrome-rgb) / 0.55);
}
.gt-js .gt-header--overlay .gt-nav__ask { text-shadow: none; }
.gt-js .gt-header--overlay.is-pinned .gt-nav__links a { text-shadow: none; }

/* Focus rings must clear the photograph, not just the scrim — the same problem
   §11a already solved for the hero, and now the header's too, because the bar
   is on the picture. The site ring is --gt-focus-dark (Ember) and it holds at
   5.9:1 on flat chrome, but measured over this frame it falls to about 2.6:1
   at the worst pixel behind the link row, under the 3:1 a non-text indicator
   needs. Paper clears it everywhere, and is what the hero uses two sections
   down. Kept through .is-pinned as well: a focus ring that changes colour
   depending on how far the page is scrolled is worse than one that does not,
   and paper on chrome is 16.9:1. */
.gt-js .gt-header--overlay a:focus-visible,
.gt-js .gt-header--overlay button:focus-visible {
  outline: 3px solid var(--gt-paper);
  outline-offset: 2px;
}

/* Inside the open mobile panel the links are back on a solid chrome sheet —
   it is a menu, not part of the photograph — so they drop the shadow they
   needed over the picture. (The panel itself already starts at the bar's real
   bottom edge: §10's mobile rule reads --gt-header-h.) */
@media (max-width: 900px) {
  .gt-js .gt-header--overlay .gt-nav__links a { text-shadow: none; }
}


/* ==========================================================================
   §11  HERO
   ========================================================================== */
.gt-hero {
  position: relative;
  background: var(--gt-chrome);
  color: var(--gt-text-on-dark);
  padding: var(--gt-space-12) 0 var(--gt-space-12);
  border-bottom: 1px solid var(--gt-chrome-line);
  overflow: hidden;
  --gt-c-text:            var(--gt-text-on-dark);
  --gt-c-text-secondary:  var(--gt-text-secondary-on-dark);
  --gt-c-text-muted:      var(--gt-text-secondary-on-dark);
  --gt-c-link:            var(--gt-link-on-dark);
  --gt-c-link-hover:      var(--gt-link-on-dark-hover);
  --gt-c-border:          var(--gt-border-dark);
  --gt-c-border-strong:   var(--gt-border-strong-dark);
  --gt-c-focus:           var(--gt-focus-dark);
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-chrome);
  --gt-c-surface:         var(--gt-surface-dark);
  --gt-c-surface-alt:     var(--gt-surface-dark-elevated);
  --gt-c-warm:            var(--gt-ember);
}
@media (max-width: 640px) { .gt-hero { padding: var(--gt-space-10) 0 var(--gt-space-8); } }

.gt-hero__content { max-width: 46rem; position: relative; z-index: 2; }
.gt-hero h1 { margin-bottom: var(--gt-space-4); }
.gt-hero__actions {
  display: flex;
  gap: var(--gt-space-3);
  margin-top: var(--gt-space-8);
  flex-wrap: wrap;
}
/* Stat strip: a single water rule beneath the hero, not a row of tiles. */
.gt-hero__stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: var(--gt-space-5);
  margin-top: var(--gt-space-12);
  padding-top: var(--gt-space-5);
  border-top: 1px solid var(--gt-water-lift-2);
  position: relative;
  z-index: 2;
}
.gt-hero__stat strong {
  display: block;
  font-family: var(--gt-font-display);
  font-weight: 600;
  font-size: var(--gt-fs-h4);
  color: var(--gt-text-on-dark);
  margin-bottom: 2px;
}
.gt-hero__stat span {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.05em;
  color: var(--gt-text-secondary-on-dark);
}

/* --------------------------------------------------------------------------
   §11a  PHOTOGRAPHIC HERO  —  .gt-hero--photo

   The homepage opens on a photograph instead of a solid chrome slab. Only
   .gt-hero gains this modifier; every other surface, the header, the type
   scale, the copy and the palette are untouched.

   PALETTE DISCIPLINE
     No new colour. The scrim is a single approved token, --gt-chrome, at
     partial alpha through the existing --gt-chrome-rgb channel. Water was
     considered for the base of the scrim and deliberately rejected: it would
     have needed a third translucency channel in §1, and the base reads
     correctly as neutral chrome with the existing --gt-water-lift-2 hairline
     carrying the edge.

   SCRIM STRENGTH
     Every alpha below was tuned against real composited pixels of this
     photograph — the image drawn through the same cover mapping the browser
     uses, these gradients painted over it, then the background luminance read
     back under the line boxes of each piece of hero copy. Nothing here is
     estimated against a flat background token, which is the mistake that made
     the first attempt at a photographic hero so dark.

     The review study Bobby saw ran roughly 0.85 effective alpha through the
     text band. It cleared WCAG comfortably and read as a dark block with a
     picture faintly behind it. Mean composited luminance of the hero, review
     scrim vs this one:

       1600 px   0.0201 -> 0.0502     (2.5x)
       1280 px   0.0213 -> 0.0529     (2.5x)
        768 px   0.0338 -> 0.0558     (1.7x)
        390 px   0.0433 -> 0.0727     (1.7x)

     and the worst text element still measures 4.68:1 or better at every width,
     against a 4.5:1 floor.

     The binding constraints are the lede, and the mono stat labels where they
     cross the sunlit limestone bar — which is why the vertical gradient gains
     weight through its lower half rather than uniformly. Darkening the top
     would only cost sky the copy does not need.

     If the photograph is ever replaced, re-measure. These numbers belong to
     this frame: a dark forested left slope, bright sky and snow through the
     centre, turquoise water and pale gravel across the base. A brighter frame
     needs more.

   HEIGHT
     Bounded by min-height rather than grown by padding, and the stat strip is
     pulled in, so "Where do you want to fish?" starts near the fold instead of
     below it. Nothing is hidden and no copy is cut.
   -------------------------------------------------------------------------- */

.gt-hero--photo {
  isolation: isolate;
  display: flex;
  align-items: center;
  /* Chrome stays behind the photograph as the fallback paint, so a failed
     image decode degrades to today's hero rather than to white. */
  background: var(--gt-chrome);
  min-height: clamp(400px, 56vh, 540px);
  padding: var(--gt-space-8) 0;
  border-bottom-color: var(--gt-water-lift-2);

  /* Two token swaps, approved for the photographic hero only.

     .gt-hero sets --gt-c-warm: var(--gt-ember), so the eyebrow renders
     #D07A46. Ember is a correct 5.9:1 kicker ON CHROME. Over a photograph it
     cannot hold: measured, it needs the ground beneath it pushed past 90%
     opacity to reach 4.5:1, which means a black band across the top of the
     hero — the exact failure this treatment exists to avoid. Small warm text
     over a picture is the wrong tool.

     Same argument one tier down for --gt-on-dark-muted (#C9C4BB): a 10.9:1
     secondary tone on flat chrome, but 3.6-4.2:1 on a photograph. Rather than
     crush the image to rescue a muted tier that was never designed for a
     variable ground, secondary text on the photographic hero is promoted to
     paper, and hierarchy is carried by size, weight and family instead —
     which is how this system prefers to carry it anyway.

     Palette RULE 03 states the principle: on dark, links and labels are
     PAPER; contrast is solved by neutrals, never by brightening the brand.
     RULE 04 is still satisfied — Ember remains the one warm signal on chrome
     everywhere else, including the section eyebrows further down this page. */
  --gt-c-warm:           var(--gt-on-dark);
  --gt-c-text-secondary: var(--gt-on-dark);
  --gt-c-text-muted:     var(--gt-on-dark);
}

/* Under the overlay header (§10a) the hero's box now starts at the top of the
   document, so the photograph fills the strip the navigation sits on. Pay the
   header's height back as padding — the hero is a centred flex box, so this
   re-centres the copy in the space below the bar instead of pushing it down —
   and grow min-height by the same amount, so the picture below the navigation
   is exactly as tall as it was before. Nothing about the approved composition
   moves; it gains a header's worth of sky above it. */
.gt-js .gt-header--overlay + main .gt-hero--photo {
  min-height: calc(clamp(400px, 56vh, 540px) + var(--gt-header-h));
  padding-top: calc(var(--gt-space-8) + var(--gt-header-h));
}
@media (max-width: 720px) {
  .gt-js .gt-header--overlay + main .gt-hero--photo {
    min-height: calc(clamp(320px, 48vh, 420px) + var(--gt-header-h));
    padding-top: calc(var(--gt-space-5) + var(--gt-header-h));
  }
}

/* NAVIGATION BAND — the readability ground behind the wordmark and the links.
   Same token, same channel, same technique as the rest of the scrim: pure
   --gt-chrome at partial alpha. No new colour, and nothing is blurred.

   Anchored in px off --gt-header-h rather than in %, so it tracks the bar it
   exists for instead of the hero's height: full weight across the bar, half of
   it gone one bar-height down, and nothing at all by 2.6 bar-heights (~166px
   desktop). That is what keeps it a gradient rather than the rectangular strip
   this change exists to remove — and it lands entirely in sky, so the approved
   lighter treatment through the body of the frame is untouched.

   Alphas set by measurement, not estimate, by the same method §11a used: the
   photograph drawn through the browser's own cover mapping, every scrim layer
   composited over it from its COMPUTED value, and the background luminance
   read back under the line box of each header element, at all five review
   widths. Measured worst case per width (worst single pixel, which is stricter
   than the mean §11a quotes) — wordmark / worst nav link:

     1600   8.16 / 8.40      1280   8.97 / 7.89      768   6.30 / n-a
      390   7.82 / n-a        320   8.18 / n-a       (n-a: below 901px the
   links live in the solid chrome panel, not on the photograph.)

   These landed deliberately high. A first pass ran roughly twice these alphas;
   it measured beautifully and cost the top of the frame a third of its light
   for contrast nobody needed, so it was pulled back to the gentlest band that
   still anchors the bar. Mean hero luminance against the approved Hero A
   baseline recorded in §11a:

     1600   0.0502 -> 0.0486      1280   0.0529 -> 0.0510      768  0.0558 -> 0.0517
      390   0.0727 -> 0.0684

   i.e. 3-7% — the approved lighter treatment, kept. Replace the photograph and
   every number here has to be measured again with it. */
.gt-js .gt-header--overlay + main .gt-hero__scrim {
  --gt-hero-nav-band: linear-gradient(
    to bottom,
    rgb(var(--gt-chrome-rgb) / 0.30) 0,
    rgb(var(--gt-chrome-rgb) / 0.26) calc(var(--gt-header-h) * 0.5),
    rgb(var(--gt-chrome-rgb) / 0.17) var(--gt-header-h),
    rgb(var(--gt-chrome-rgb) / 0.06) calc(var(--gt-header-h) * 1.8),
    rgb(var(--gt-chrome-rgb) / 0)    calc(var(--gt-header-h) * 2.6)
  );
}

.gt-hero__photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Focal point: holds the snow notch and the river bend in frame as the
     hero box changes aspect from a wide desktop strip to a tall phone one. */
  object-position: 54% 46%;
}

/* Readability scrim. Two stacked gradients, both pure --gt-chrome.

   Vertical  — marries the top edge into the dark header and settles the base
               so the stat strip keeps its contrast, without a second slab.
   Horizontal— weights the left, where the headline, lede and CTAs sit, and
               releases the right so the water and the far ridge stay visible.

   Deliberately NOT a flat overlay: a flat wash strong enough to pass contrast
   turns the photograph into texture. */
.gt-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* Navigation band. Empty by default — it only exists under the overlay
     header (§10a), and is defined there so both scrim variants below can carry
     it without restating the two tuned gradients. */
  --gt-hero-nav-band: linear-gradient(rgb(var(--gt-chrome-rgb) / 0), rgb(var(--gt-chrome-rgb) / 0));
  background:
    var(--gt-hero-nav-band),
    linear-gradient(
      to bottom,
      rgb(var(--gt-chrome-rgb) / 0.38) 0%,
      rgb(var(--gt-chrome-rgb) / 0.10) 30%,
      rgb(var(--gt-chrome-rgb) / 0.20) 58%,
      rgb(var(--gt-chrome-rgb) / 0.46) 80%,
      rgb(var(--gt-chrome-rgb) / 0.56) 100%
    ),
    linear-gradient(
      to right,
      rgb(var(--gt-chrome-rgb) / 0.50) 0%,
      rgb(var(--gt-chrome-rgb) / 0.46) 48%,
      rgb(var(--gt-chrome-rgb) / 0.34) 68%,
      rgb(var(--gt-chrome-rgb) / 0.12) 86%,
      rgb(var(--gt-chrome-rgb) / 0.02) 100%
    );
}

/* .gt-hero__content already carries z-index 2; the wrap establishes itself
   above the scrim so nothing depends on a stacking accident. */
.gt-hero--photo > .gt-wrap { position: relative; z-index: 2; width: 100%; }

/* Type on a photograph needs a little more separation than type on a flat
   ground. A shadow, not a heavier scrim — it costs the image nothing. */
.gt-hero--photo h1,
.gt-hero--photo .gt-lede,
.gt-hero--photo .gt-eyebrow,
.gt-hero--photo .gt-hero__stat strong { text-shadow: 0 1px 3px rgb(var(--gt-chrome-rgb) / 0.55); }
.gt-hero--photo .gt-hero__stat span   { text-shadow: 0 1px 3px rgb(var(--gt-chrome-rgb) / 0.65); }

/* Pull the stat strip in. This is most of the height the solid hero spent. */
.gt-hero--photo .gt-hero__stats {
  margin-top: var(--gt-space-6);
  padding-top: var(--gt-space-4);
  gap: var(--gt-space-4) var(--gt-space-5);
}
.gt-hero--photo .gt-hero__actions { margin-top: var(--gt-space-6); }

/* The secondary CTA is an outlined button on what is now a photograph. Back
   its face just enough that the outline never floats on a pale patch of sky. */
.gt-hero--photo .gt-btn--secondary {
  background: rgb(var(--gt-chrome-rgb) / 0.24);
  backdrop-filter: blur(2px);
}

/* The horizontal weighting above is only correct while the text column is a
   fraction of the viewport. Below roughly 1024px the copy and the stat strip
   span the full width, so the right-hand falloff lands underneath text instead
   of beside it — measured, not assumed. From tablet down, drop the horizontal
   layer and weight the scrim vertically instead. */
@media (max-width: 1023px) {
  .gt-hero__scrim {
    background:
      var(--gt-hero-nav-band),
      linear-gradient(
        to bottom,
        rgb(var(--gt-chrome-rgb) / 0.44) 0%,
        rgb(var(--gt-chrome-rgb) / 0.40) 26%,
        rgb(var(--gt-chrome-rgb) / 0.55) 52%,
        rgb(var(--gt-chrome-rgb) / 0.68) 72%,
        rgb(var(--gt-chrome-rgb) / 0.72) 100%
      );
  }
}

/* Phone. Height here is set by content, not by min-height, so compaction has
   to come out of the vertical rhythm. Nothing is hidden and no copy is cut:
   both CTAs, all three stats, the lede and the headline are still present. The
   stat strip simply becomes two columns, so three tiles cost two rows. */
@media (max-width: 720px) {
  .gt-hero--photo {
    min-height: clamp(320px, 48vh, 420px);
    padding: var(--gt-space-5) 0;
  }
  .gt-hero--photo h1 { margin-bottom: var(--gt-space-3); }
  .gt-hero--photo .gt-lede { font-size: var(--gt-fs-body); }
  .gt-hero--photo .gt-hero__actions { margin-top: var(--gt-space-5); gap: var(--gt-space-2); }
  .gt-hero--photo .gt-hero__stats {
    grid-template-columns: 1fr 1fr;
    margin-top: var(--gt-space-5);
    padding-top: var(--gt-space-3);
    gap: var(--gt-space-3) var(--gt-space-4);
  }
  /* The third tile takes the full second row rather than leaving a hole. */
  .gt-hero--photo .gt-hero__stat:nth-child(3) { grid-column: 1 / -1; }
}

/* Focus rings must clear the photograph, not just the scrim. */
.gt-hero--photo a:focus-visible,
.gt-hero--photo button:focus-visible {
  outline: 3px solid var(--gt-paper);
  outline-offset: 2px;
}

/* Interior page hero — paper, quieter, still clearly a page opening. */
.gt-page-hero {
  padding: var(--gt-space-10) 0 var(--gt-space-8);
  background: var(--gt-bg);
  border-bottom: 1px solid var(--gt-border-strong);
}
.gt-page-hero h1 { max-width: 24ch; }
.gt-page-hero .gt-lede { margin-top: var(--gt-space-4); }

.gt-breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.05em;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  margin-bottom: var(--gt-space-5);
}
.gt-breadcrumbs a { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
.gt-breadcrumbs a:hover { color: var(--gt-c-link-hover, var(--gt-link-hover)); border-bottom-color: currentColor; }
.gt-breadcrumbs span[aria-hidden] { opacity: 0.6; }


/* ==========================================================================
   §12  CARDS
   One structural system. Destination, water, journal and resource cards are
   the same object with different content slots — not four designs.
   ========================================================================== */
.gt-card {
  background: var(--gt-c-surface, var(--gt-surface));
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-md);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
a.gt-card { text-decoration: none; color: inherit; }
a.gt-card:hover {
  border-color: var(--gt-c-border-strong, var(--gt-border-strong));
  box-shadow: var(--gt-shadow-sm);
}

.gt-card__media {
  aspect-ratio: 3 / 2;
  background: var(--gt-water-wash);
  border-bottom: 1px solid var(--gt-c-border, var(--gt-border));
  display: flex;
  align-items: flex-end;
  padding: var(--gt-space-3);
  position: relative;
}
.gt-surface-chrome .gt-card__media,
.gt-section--panel .gt-card__media,
.gt-hero .gt-card__media { background: var(--gt-water); }

/* Region / country tag riding on the media slot. */
.gt-card__tag {
  position: relative;
  z-index: 2;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  background: var(--gt-water);
  color: var(--gt-on-dark);
  padding: 4px 8px;
  border-radius: var(--gt-radius-xs);
}

.gt-card__body {
  padding: var(--gt-space-5);
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--gt-space-2);
}
.gt-card__body h3 { margin: 0; }
.gt-card__meta {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.05em;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-card__desc {
  font-size: var(--gt-fs-body-sm);
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-card__footer {
  margin-top: auto;
  padding-top: var(--gt-space-4);
  font-size: var(--gt-fs-body-sm);
  font-weight: 600;
  color: var(--gt-c-link, var(--gt-link));
}
a.gt-card:hover .gt-card__footer { color: var(--gt-c-link-hover, var(--gt-link-hover)); }
.gt-card__footer.gt-muted { color: var(--gt-c-text-secondary, var(--gt-text-secondary)); font-weight: 500; }

/* Card detail row — species, access, season. Degrades honestly: a row whose
   value is unknown is simply not rendered by the page, and the card still
   reads as complete. */
.gt-card__facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gt-space-1) var(--gt-space-4);
  padding-top: var(--gt-space-3);
  margin-top: var(--gt-space-1);
  border-top: 1px solid var(--gt-c-border, var(--gt-border));
}
.gt-card__fact {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-card__fact b {
  display: block;
  font-family: var(--gt-font-body);
  font-size: var(--gt-fs-body-sm);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--gt-c-text, var(--gt-text));
}


/* ==========================================================================
   §13  DATA & INTELLIGENCE
   Structured fishing intelligence, styled to sit inside an editorial page
   rather than to look like a separate analytics product.
   Nothing here invents data: every component has an explicit "unknown" state.
   ========================================================================== */

/* -- Intelligence card -- */
.gt-intel-card {
  background: var(--gt-c-surface, var(--gt-surface));
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-left: 3px solid var(--gt-water-lift-2);
  border-radius: var(--gt-radius-md);
  padding: var(--gt-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--gt-space-3);
}
.gt-intel-card__kicker {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gt-space-2);
  flex-wrap: wrap;
}
.gt-intel-badge {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-warm, var(--gt-rust));
}
.gt-intel-card__signal,
.gt-intel-card p { font-size: var(--gt-fs-body-sm); color: var(--gt-c-text-secondary, var(--gt-text-secondary)); }
.gt-intel-card h3, .gt-intel-card h4 { font-size: var(--gt-fs-h4); }
.gt-intel-card__cta {
  margin-top: auto;
  padding-top: var(--gt-space-2);
  font-size: var(--gt-fs-body-sm);
  font-weight: 600;
  color: var(--gt-c-link, var(--gt-link));
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.gt-intel-card__cta:hover { color: var(--gt-c-link-hover, var(--gt-link-hover)); text-decoration: underline; text-underline-offset: 3px; }

/* -- Stat / reading tile -- */
.gt-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: 1px;
  background: var(--gt-c-border, var(--gt-border));
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-md);
  overflow: hidden;
}
.gt-stat {
  background: var(--gt-c-surface, var(--gt-surface));
  padding: var(--gt-space-5) var(--gt-space-4);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.gt-stat__value {
  font-family: var(--gt-font-display);
  font-weight: 600;
  font-size: var(--gt-fs-stat);
  line-height: 1.05;
  letter-spacing: var(--gt-ls-heading);
  color: var(--gt-c-text, var(--gt-text));
  font-variant-numeric: tabular-nums;
}
.gt-stat__value--unknown {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-h4);
  font-weight: 400;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-stat__label {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-stat__unit { font-size: 0.5em; font-weight: 500; margin-left: 2px; }

/* -- Freshness / source attribution line -- */
.gt-source-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gt-space-2) var(--gt-space-4);
  padding-top: var(--gt-space-3);
  border-top: 1px solid var(--gt-c-border, var(--gt-border));
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.05em;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-source-line a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.gt-source-line a:hover { color: var(--gt-c-link-hover, var(--gt-link-hover)); }

/* -- Confidence / evidence meter. The label is always spelled out, so the
      bar is a redundant encoding rather than the only signal. -- */
.gt-confidence { display: flex; flex-direction: column; gap: 6px; }
.gt-confidence__head {
  display: flex;
  justify-content: space-between;
  gap: var(--gt-space-3);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-confidence__track {
  height: 5px;
  border-radius: var(--gt-radius-xs);
  background: var(--gt-c-surface-alt, var(--gt-bg-secondary));
  border: 1px solid var(--gt-c-border, var(--gt-border));
  overflow: hidden;
}
.gt-confidence__fill { height: 100%; background: var(--gt-water-lift-2); }
.gt-surface-paper .gt-confidence__fill { background: var(--gt-water); }

/* -- Data row list (river sections, regulations, hatch windows) -- */
.gt-row-list { display: flex; flex-direction: column; }
.gt-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--gt-space-4);
  padding: var(--gt-space-4) 0;
  border-bottom: 1px solid var(--gt-c-border, var(--gt-border));
}
.gt-row:last-child { border-bottom: none; }
.gt-row__label { font-weight: 600; color: var(--gt-c-text, var(--gt-text)); }
.gt-row__value { color: var(--gt-c-text-secondary, var(--gt-text-secondary)); text-align: right; }
.gt-row__value--num { font-family: var(--gt-font-mono); font-variant-numeric: tabular-nums; }
/* Missing data is stated, never faked into false precision. */
.gt-row__value--unknown { font-family: var(--gt-font-mono); font-size: var(--gt-fs-caption); }


/* ==========================================================================
   §14  TAGS, CHIPS, STATUS, ALERTS
   Colour appears here only where it carries meaning, and never alone: every
   status is glyph + word + colour, per the approved palette's own rule.
   ========================================================================== */

/* Neutral descriptive tag — species, method, trip type. No colour coding:
   these classify, they do not signal state. */
.gt-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  background: transparent;
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-xs);
  padding: 4px 8px;
}
.gt-tag-row { display: flex; flex-wrap: wrap; gap: var(--gt-space-2); }

/* Interactive filter chip. */
.gt-chip {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 8px 14px;
  font-size: var(--gt-fs-body-sm);
  font-weight: 500;
  color: var(--gt-c-text, var(--gt-text));
  background: var(--gt-c-surface, var(--gt-surface));
  border: 1px solid var(--gt-c-border-strong, var(--gt-border-strong));
  border-radius: var(--gt-radius-xs);
  cursor: pointer;
  transition: background-color 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.gt-chip:hover { border-color: var(--gt-c-text, var(--gt-text)); }
/* Selected is fill + border + aria-pressed, not colour alone. */
.gt-chip[aria-pressed="true"] {
  background: var(--gt-c-accent, var(--gt-accent));
  color: var(--gt-c-on-accent, var(--gt-on-accent));
  border-color: var(--gt-c-accent, var(--gt-accent));
}
.gt-chip-row { display: flex; flex-wrap: wrap; gap: var(--gt-space-2); }

/* Status badge. The glyph and the word are mandatory; the colour is the
   third, redundant signal. */
.gt-status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  border: 1px solid currentColor;
  border-radius: var(--gt-radius-xs);
  padding: 4px 8px;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-status-badge__glyph { font-size: 0.9em; line-height: 1; }
.gt-status-badge--good    { color: var(--gt-c-success, var(--gt-success)); }
.gt-status-badge--caution { color: var(--gt-c-warning, var(--gt-warning)); }
.gt-status-badge--closed  { color: var(--gt-c-error, var(--gt-error)); }
.gt-status-badge--report  { color: var(--gt-c-text-secondary, var(--gt-text-secondary)); }

/* Alerts / callouts. */
.gt-alert {
  display: flex;
  gap: var(--gt-space-3);
  align-items: flex-start;
  padding: var(--gt-space-4) var(--gt-space-5);
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-left-width: 3px;
  border-radius: 0 var(--gt-radius-sm) var(--gt-radius-sm) 0;
  font-size: var(--gt-fs-body-sm);
  background: var(--gt-c-surface, var(--gt-surface));
  color: var(--gt-c-text, var(--gt-text));
}
.gt-alert strong { display: block; margin-bottom: 2px; font-weight: 600; }
.gt-alert__glyph { flex-shrink: 0; line-height: 1.5; }
.gt-alert--info    { background: var(--gt-wash-info); border-color: var(--gt-wash-info-border); border-left-color: var(--gt-water); color: var(--gt-ink); }
.gt-alert--success { border-left-color: var(--gt-success); }
.gt-alert--warning { background: var(--gt-wash-warm); border-color: var(--gt-rust-wash); border-left-color: var(--gt-warning); color: var(--gt-ink); }
.gt-alert--error   { border-left-color: var(--gt-error); }

/* Legacy callout markup, re-pointed onto the alert system. */
.gt-callout {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--gt-space-4);
  flex-wrap: wrap;
  padding: var(--gt-space-5);
  background: var(--gt-wash-info);
  border: 1px solid var(--gt-wash-info-border);
  border-left: 3px solid var(--gt-water);
  border-radius: 0 var(--gt-radius-sm) var(--gt-radius-sm) 0;
  color: var(--gt-ink);
  --gt-c-text: var(--gt-ink);
  --gt-c-text-secondary: var(--gt-ink-muted);
  --gt-c-link: var(--gt-water);
  --gt-c-link-hover: var(--gt-rust);
}
.gt-callout p { margin: 0; font-size: var(--gt-fs-body-sm); color: var(--gt-ink-muted); }
.gt-callout strong { font-family: var(--gt-font-display); font-size: var(--gt-fs-h4); font-weight: 600; display: block; margin-bottom: 2px; color: var(--gt-ink); }
.gt-callout--river { background: var(--gt-wash-warm); border-color: var(--gt-rust-wash); border-left-color: var(--gt-rust); }

/* Honest "needs human/legal review" and "demo data" notices. */
.gt-legal-notice {
  display: flex;
  flex-direction: column;
  gap: var(--gt-space-2);
  background: var(--gt-wash-warm);
  border: 1px solid var(--gt-rust-wash);
  border-left: 3px solid var(--gt-warning);
  border-radius: 0 var(--gt-radius-sm) var(--gt-radius-sm) 0;
  padding: var(--gt-space-4) var(--gt-space-5);
  margin-bottom: var(--gt-space-6);
  font-size: var(--gt-fs-body-sm);
  color: var(--gt-ink);
}
.gt-legal-notice strong { color: var(--gt-ink); font-weight: 600; }
.gt-legal-notice span { color: var(--gt-ink-muted); }

.gt-demo-flag {
  display: inline-flex;
  align-items: center;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  border: 1px dashed var(--gt-c-border-strong, var(--gt-border-strong));
  border-radius: var(--gt-radius-xs);
  padding: 3px 8px;
}

/* Panels and honest placeholders. */
.gt-panel {
  background: var(--gt-c-surface, var(--gt-surface));
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-md);
  padding: var(--gt-space-6);
}
.gt-panel--elevated { box-shadow: var(--gt-shadow-sm); }
.gt-placeholder {
  border: 1px dashed var(--gt-c-border-strong, var(--gt-border-strong));
  border-radius: var(--gt-radius-md);
  padding: var(--gt-space-5);
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  font-size: var(--gt-fs-body-sm);
  background: transparent;
}
.gt-placeholder strong { color: var(--gt-c-text, var(--gt-text)); display: block; margin-bottom: 4px; }

/* Feature row (three-up explanation grids). */
.gt-feature { display: flex; flex-direction: column; gap: var(--gt-space-2); }
.gt-feature__icon {
  width: 40px; height: 40px;
  border-radius: var(--gt-radius-sm);
  background: var(--gt-c-surface-alt, var(--gt-bg-secondary));
  border: 1px solid var(--gt-c-border, var(--gt-border));
  display: flex; align-items: center; justify-content: center;
  color: var(--gt-c-text, var(--gt-text));
  font-size: 1.1rem;
  margin-bottom: var(--gt-space-2);
}
.gt-feature h3 { font-size: var(--gt-fs-h4); }
.gt-feature p { color: var(--gt-c-text-secondary, var(--gt-text-secondary)); font-size: var(--gt-fs-body-sm); }


/* ==========================================================================
   §15  FORMS
   Every control has a visible border at >=3:1 against its own surface, so
   the field is findable without relying on placeholder text or colour.
   Errors carry a glyph and a message, never colour alone.
   ========================================================================== */
.gt-field { display: flex; flex-direction: column; gap: 6px; }
.gt-field label,
.gt-field .gt-field__label {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-field input,
.gt-field select,
.gt-field textarea,
.gt-input {
  width: 100%;
  min-height: 44px;
  padding: 11px 13px;
  background: var(--gt-c-surface, var(--gt-surface));
  border: 1px solid var(--gt-c-border-strong, var(--gt-border-strong));
  border-radius: var(--gt-radius-sm);
  color: var(--gt-c-text, var(--gt-text));
  font-size: var(--gt-fs-body-sm);
  line-height: var(--gt-lh-ui);
}
.gt-field textarea, textarea.gt-input { min-height: 104px; resize: vertical; }
.gt-field input::placeholder,
.gt-field textarea::placeholder,
.gt-input::placeholder { color: var(--gt-c-text-secondary, var(--gt-text-secondary)); opacity: 1; }
.gt-field input:hover,
.gt-field select:hover,
.gt-field textarea:hover { border-color: var(--gt-c-text, var(--gt-text)); }

.gt-field__hint { font-size: var(--gt-fs-caption); color: var(--gt-c-text-secondary, var(--gt-text-secondary)); }
.gt-field__error {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: var(--gt-fs-caption);
  font-weight: 600;
  color: var(--gt-c-error, var(--gt-error));
}
.gt-field--error input,
.gt-field--error select,
.gt-field--error textarea {
  border-color: var(--gt-c-error, var(--gt-error));
  border-width: 2px;
}
.gt-field--success input { border-color: var(--gt-c-success, var(--gt-success)); }
.gt-field input[disabled],
.gt-field select[disabled],
.gt-field textarea[disabled] {
  background: var(--gt-c-surface-alt, var(--gt-bg-secondary));
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  border-style: dashed;
  cursor: not-allowed;
}

/* Checkbox and radio keep the native control but adopt the brand colour. */
.gt-check {
  display: flex;
  align-items: flex-start;
  gap: var(--gt-space-3);
  font-size: var(--gt-fs-body-sm);
  color: var(--gt-c-text, var(--gt-text));
  cursor: pointer;
}
.gt-check input[type="checkbox"],
.gt-check input[type="radio"] {
  width: 18px; height: 18px;
  min-height: 0;
  margin: 3px 0 0;
  flex-shrink: 0;
  accent-color: var(--gt-c-accent, var(--gt-accent));
}
.gt-form-row {
  display: grid;
  gap: var(--gt-space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
}


/* ==========================================================================
   §16  ASK GHOST TOWN
   The product surface is a WATER panel: the same brand, one step away from
   the editorial page, never a third-party chatbot skin.
   ========================================================================== */
.gt-ask {
  background: var(--gt-water);
  color: var(--gt-on-dark);
  border-radius: var(--gt-radius-lg);
  padding: var(--gt-space-6);
  --gt-c-bg:              var(--gt-water);
  --gt-c-surface:         var(--gt-water-lift-1);
  --gt-c-surface-alt:     var(--gt-water-lift-1);
  --gt-c-text:            var(--gt-on-dark);
  --gt-c-text-secondary:  var(--gt-on-dark-muted);
  --gt-c-text-muted:      var(--gt-on-dark-muted);
  --gt-c-link:            var(--gt-on-dark);
  --gt-c-link-hover:      var(--gt-on-dark);
  --gt-c-border:          var(--gt-water-lift-2);
  --gt-c-border-strong:   var(--gt-on-dark-muted);
  --gt-c-focus:           var(--gt-paper);
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-water);
  --gt-c-warm:            var(--gt-on-dark);
}
.gt-ask__entry {
  display: flex;
  flex-direction: column;
  gap: var(--gt-space-4);
}
.gt-ask__form { display: flex; gap: var(--gt-space-3); flex-wrap: wrap; }
.gt-ask__form .gt-input { flex: 1 1 16rem; }

/* Conversation surface. */
.gt-ask__thread { display: flex; flex-direction: column; gap: var(--gt-space-4); margin-top: var(--gt-space-5); }
.gt-ask__msg {
  padding: var(--gt-space-4) var(--gt-space-5);
  border-radius: var(--gt-radius-md);
  font-size: var(--gt-fs-body-sm);
  max-width: 52ch;
}
/* The angler's own words: paper block, near-black type. */
.gt-ask__msg--user {
  align-self: flex-end;
  background: var(--gt-paper);
  color: var(--gt-ink);
}
/* Ghost Town's answer: the elevated water step, with a warm rule so the two
   speakers are told apart by position AND edge, not by colour alone. */
.gt-ask__msg--gt {
  align-self: flex-start;
  background: var(--gt-water-lift-1);
  color: var(--gt-on-dark);
  border-left: 3px solid var(--gt-water-lift-2);
  max-width: 62ch;
}
.gt-ask__msg--gt strong { color: var(--gt-on-dark); }

/* Citations under an answer. */
.gt-ask__cites {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: var(--gt-space-3);
  padding-top: var(--gt-space-3);
  border-top: 1px solid var(--gt-water-lift-2);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
  color: var(--gt-on-dark-muted);
}
.gt-ask__cites a { color: var(--gt-on-dark); text-decoration: underline; text-underline-offset: 3px; }

/* A recommended river / destination / fly inside an answer. */
.gt-ask__rec {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--gt-space-4);
  flex-wrap: wrap;
  margin-top: var(--gt-space-3);
  padding: var(--gt-space-3) var(--gt-space-4);
  background: var(--gt-water);
  border: 1px solid var(--gt-water-lift-2);
  border-radius: var(--gt-radius-sm);
}
.gt-ask__rec b { font-family: var(--gt-font-display); font-size: var(--gt-fs-h4); font-weight: 600; }

/* Status / loading / error. */
.gt-status { display: block; font-size: var(--gt-fs-body-sm); color: var(--gt-c-text-secondary, var(--gt-text-secondary)); }
.gt-ask__loading {
  display: inline-flex;
  align-items: center;
  gap: var(--gt-space-2);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-on-dark-muted);
}
.gt-ask__loading::before {
  content: "";
  width: 11px; height: 11px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: gt-spin 0.7s linear infinite;
}
.gt-ask__error {
  display: flex;
  gap: var(--gt-space-2);
  padding: var(--gt-space-3) var(--gt-space-4);
  background: var(--gt-water-lift-1);
  border: 1px solid var(--gt-closed-dark);
  border-radius: var(--gt-radius-sm);
  font-size: var(--gt-fs-body-sm);
  color: var(--gt-on-dark);
}


/* ==========================================================================
   §17  FOOTER
   A full chrome band: the page ends on a deliberate dark endpoint with the
   approved reversed wordmark.
   ========================================================================== */
.gt-footer {
  background: var(--gt-chrome);
  color: var(--gt-text-on-dark);
  border-top: 1px solid var(--gt-chrome-line);
  padding: var(--gt-space-12) 0 var(--gt-space-6);
  margin-top: var(--gt-space-16);
  --gt-c-text:            var(--gt-text-on-dark);
  --gt-c-text-secondary:  var(--gt-text-secondary-on-dark);
  --gt-c-link:            var(--gt-link-on-dark);
  --gt-c-link-hover:      var(--gt-link-on-dark-hover);
  --gt-c-border:          var(--gt-border-dark);
  --gt-c-border-strong:   var(--gt-border-strong-dark);
  --gt-c-focus:           var(--gt-focus-dark);
  --gt-c-warm:            var(--gt-ember);
}
.gt-footer__grid {
  display: grid;
  gap: var(--gt-space-8) var(--gt-space-6);
  grid-template-columns: 1.6fr repeat(3, 1fr);
  margin-bottom: var(--gt-space-10);
}
@media (max-width: 800px) { .gt-footer__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .gt-footer__grid { grid-template-columns: 1fr; } }

.gt-footer__brand p {
  color: var(--gt-text-secondary-on-dark);
  font-size: var(--gt-fs-body-sm);
  max-width: 34ch;
  margin-top: var(--gt-space-4);
}
.gt-footer h2, .gt-footer h4 {
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  font-weight: 500;
  letter-spacing: var(--gt-ls-mono);
  text-transform: uppercase;
  color: var(--gt-ember);
  margin-bottom: var(--gt-space-4);
}
.gt-footer ul { display: flex; flex-direction: column; gap: var(--gt-space-3); }
.gt-footer a {
  color: var(--gt-text-secondary-on-dark);
  text-decoration: none;
  font-size: var(--gt-fs-body-sm);
  border-bottom: 1px solid transparent;
}
.gt-footer a:hover { color: var(--gt-text-on-dark); border-bottom-color: var(--gt-ember); }
.gt-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gt-space-3) var(--gt-space-5);
  padding-top: var(--gt-space-5);
  border-top: 1px solid var(--gt-chrome-line);
  margin-bottom: var(--gt-space-4);
}
.gt-footer__legal a { font-family: var(--gt-font-mono); font-size: var(--gt-fs-meta); letter-spacing: 0.05em; }
.gt-footer__bottom {
  display: flex;
  justify-content: space-between;
  gap: var(--gt-space-3);
  flex-wrap: wrap;
  padding-top: var(--gt-space-5);
  border-top: 1px solid var(--gt-chrome-line);
  font-size: var(--gt-fs-caption);
  color: var(--gt-text-secondary-on-dark);
}


/* ==========================================================================
   §18  LONG-FORM, UTILITIES, FOCUS, MOTION, MEDIA
   ========================================================================== */

/* -- Editorial prose -- */
.gt-prose { max-width: var(--gt-w-read); }
.gt-prose h2 { font-size: var(--gt-fs-h2); margin: var(--gt-space-10) 0 var(--gt-space-4); }
.gt-prose h2:first-child { margin-top: 0; }
.gt-prose h3 { font-size: var(--gt-fs-h3); margin: var(--gt-space-6) 0 var(--gt-space-3); }
.gt-prose p { margin-bottom: var(--gt-space-5); color: var(--gt-c-text-secondary, var(--gt-text-secondary)); }
.gt-prose ul, .gt-prose ol {
  list-style: disc;
  padding-left: 22px;
  margin: 0 0 var(--gt-space-5);
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
  display: flex;
  flex-direction: column;
  gap: var(--gt-space-2);
}
.gt-prose ol { list-style: decimal; }
.gt-prose strong { color: var(--gt-c-text, var(--gt-text)); font-weight: 600; }
.gt-prose blockquote {
  margin: var(--gt-space-6) 0;
  padding-left: var(--gt-space-5);
  border-left: 3px solid var(--gt-water-lift-2);
  font-family: var(--gt-font-display);
  font-style: italic;
  font-size: var(--gt-fs-body-lg);
  color: var(--gt-c-text, var(--gt-text));
}
.gt-article-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gt-space-2) var(--gt-space-3);
  align-items: center;
  margin-top: var(--gt-space-4);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.05em;
  color: var(--gt-c-text-secondary, var(--gt-text-secondary));
}
.gt-article-meta span[aria-hidden] { opacity: 0.6; }

/* -- Skip link: first tab stop on every page -- */
.gt-skip-link {
  position: absolute;
  left: var(--gt-space-4);
  top: -100px;
  z-index: 999;
  background: var(--gt-paper);
  color: var(--gt-ink);
  border: 2px solid var(--gt-water);
  font-weight: 600;
  font-size: var(--gt-fs-body-sm);
  padding: 12px 18px;
  border-radius: var(--gt-radius-sm);
  text-decoration: none;
  transition: top 0.15s ease;
}
.gt-skip-link:focus { top: var(--gt-space-4); }
main:focus { outline: none; }

/* -- Visible focus for keyboard users, site-wide. The ring is contextual, so
      it stays visible on paper and on chrome without a per-page override. -- */
:focus-visible {
  outline: 3px solid var(--gt-c-focus, var(--gt-focus));
  outline-offset: 3px;
  border-radius: 2px;
}
.gt-field input:focus-visible,
.gt-field select:focus-visible,
.gt-field textarea:focus-visible,
.gt-input:focus-visible {
  outline: 3px solid var(--gt-c-focus, var(--gt-focus));
  outline-offset: 1px;
  border-color: var(--gt-c-focus, var(--gt-focus));
}
.gt-field input:focus,
.gt-field select:focus,
.gt-field textarea:focus,
.gt-input:focus { outline: none; border-color: var(--gt-c-focus, var(--gt-focus)); }

/* -- Respect reduced-motion preferences -- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* -- Utilities -- */
.gt-visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
.gt-mt-0 { margin-top: 0 !important; }
.gt-center { text-align: center; }
.gt-center .gt-lede { margin-left: auto; margin-right: auto; }
.gt-flex { display: flex; align-items: center; gap: var(--gt-space-3); }
.gt-flex-between { display: flex; align-items: center; justify-content: space-between; gap: var(--gt-space-3); flex-wrap: wrap; }
.gt-stack { display: flex; flex-direction: column; gap: var(--gt-space-4); }
.gt-stack--lg { gap: var(--gt-space-6); }

/* -- Guard against accidental sideways scroll without breaking the sticky
      header. `overflow-x: hidden|auto` would make the header's position:sticky
      resolve against a new scroll container; `clip` does not establish one, so
      it is safe on BOTH html and body. html is included because the off-canvas
      mobile nav is position:fixed and therefore escapes a clip set only on
      body — without this it extends the document at =<900px. Verified by
      rendered QA at 320/390/768px. -- */
html, body { overflow-x: clip; }

/* ==========================================================================
   IMAGE SLOT ARCHITECTURE
   Photography direction (§27 of the phase brief): real rivers, landscapes,
   anglers in context, towns, access and travel context. No generic corporate
   outdoor stock. Slots reserve their ratio so Cumulative Layout Shift stays
   at zero before the approved photography exists.

   Usage:
     <figure class="gt-media gt-media--16x9">
       <img src="..." alt="required, descriptive" width="1600" height="900"
            loading="lazy" decoding="async" sizes="(max-width: 700px) 100vw, 33vw"
            srcset="...-800.webp 800w, ...-1600.webp 1600w">
       <figcaption class="gt-media__caption">Caption <span>Credit</span></figcaption>
     </figure>
   ========================================================================== */
.gt-media {
  position: relative;
  overflow: hidden;
  margin: 0;
  background: var(--gt-water-wash);
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-md);
}
.gt-surface-chrome .gt-media,
.gt-section--panel .gt-media,
.gt-hero .gt-media { background: var(--gt-water); }
.gt-media--16x9  { aspect-ratio: 16 / 9; }
.gt-media--3x2   { aspect-ratio: 3 / 2; }
.gt-media--4x3   { aspect-ratio: 4 / 3; }
.gt-media--21x9  { aspect-ratio: 21 / 9; }
.gt-media--1x1   { aspect-ratio: 1 / 1; }
.gt-media > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--gt-media-focal, 50% 50%);
  display: block;
}
/* Older engines without aspect-ratio still reserve height. */
@supports not (aspect-ratio: 16 / 9) {
  .gt-media { height: 0; padding-bottom: 56.25%; }
  .gt-media > img { position: absolute; inset: 0; }
}
.gt-media__caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--gt-space-3) var(--gt-space-4);
  background: rgb(var(--gt-chrome-rgb) / 0.88);
  font-size: var(--gt-fs-caption);
  color: var(--gt-on-dark);
}
.gt-media__caption span {
  display: block;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.05em;
  color: var(--gt-on-dark-muted);
}
/* A slot waiting on approved photography, marked honestly rather than filled
   with stock imagery. */
.gt-media--pending::after {
  content: "Image pending";
  position: absolute;
  right: var(--gt-space-3);
  bottom: var(--gt-space-3);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-ink-muted);
  border: 1px dashed var(--gt-water-line);
  border-radius: var(--gt-radius-xs);
  padding: 3px 8px;
}
.gt-section--panel .gt-media--pending::after,
.gt-hero .gt-media--pending::after { color: var(--gt-on-dark-muted); border-color: var(--gt-water-lift-2); }

/* Card media doubles as an image slot: dropping an <img> in needs no markup
   restructuring, and the aspect ratio is already reserved above. */
.gt-card__media > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--gt-media-focal, 50% 50%);
  z-index: 0;
}
/* Scrim appears only once a real image is present, so the tag stays legible
   over photography without changing today's image-free appearance. */
@supports selector(:has(*)) {
  .gt-card__media:has(> img)::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(to top, rgb(var(--gt-chrome-rgb) / 0.75), transparent 55%);
  }
}


/* ==========================================================================
   §19  DESTINATION PAGES

   Everything below composes the components above; none of it introduces a
   second design language, and none of it defines a brand colour. Destination
   pages are the first pages assembled by a generator rather than by hand
   (web/tools/build/Build-Destinations.ps1), so the classes here are the
   contract between that generator and this stylesheet.

   The rhythm problem this section exists to solve: the first Slovenia review
   showed too much uninterrupted paper. A destination page is long, and three
   surfaces are not enough variety over that length. So a page alternates
   paper -> alt -> WATER -> paper -> chrome, and the water band below is the
   step that was missing.
   ========================================================================== */

/* --- The water band -------------------------------------------------------
   A mid-tone blue band. Lighter than --panel, darker than --alt, and it
   carries the water surface context with it so every component inside steps
   to the right tokens rather than inheriting paper values onto blue. */
.gt-section--water {
  background: var(--gt-water);
  color: var(--gt-on-dark);
  --gt-c-bg:              var(--gt-water);
  --gt-c-surface:         var(--gt-water-lift-1);
  --gt-c-surface-alt:     var(--gt-water-lift-1);
  --gt-c-text:            var(--gt-on-dark);
  --gt-c-text-secondary:  var(--gt-on-dark-muted);
  --gt-c-text-muted:      var(--gt-on-dark-muted);
  --gt-c-link:            var(--gt-on-dark);
  --gt-c-link-hover:      var(--gt-on-dark-muted);
  --gt-c-border:          var(--gt-water-lift-2);
  --gt-c-border-strong:   var(--gt-on-dark-muted);
  --gt-c-focus:           var(--gt-paper);
  --gt-c-accent:          var(--gt-paper);
  --gt-c-accent-hover:    var(--gt-on-dark-muted);
  --gt-c-on-accent:       var(--gt-water);
  --gt-c-warm:            var(--gt-on-dark);
}
/* Same reasoning as the chrome rule in §3: a card rendering its own surface on
   a water band must not fall back to the paper palette for its own interior. */
.gt-section--water .gt-card,
.gt-section--water .gt-intel-card,
.gt-section--water .gt-panel,
.gt-section--water .gt-stat,
.gt-section--water .gt-stats {
  --gt-c-bg:              var(--gt-water-lift-1);
  --gt-c-surface:         var(--gt-water-lift-1);
  --gt-c-surface-alt:     var(--gt-water-lift-1);
  --gt-c-text:            var(--gt-on-dark);
  --gt-c-text-secondary:  var(--gt-on-dark-muted);
  --gt-c-text-muted:      var(--gt-on-dark-muted);
  --gt-c-border:          var(--gt-water-lift-2);
}
.gt-section--water .gt-eyebrow { color: var(--gt-on-dark-muted); }


/* --- Destination hero -----------------------------------------------------
   The photographic hero from the homepage, reused. The only addition is a
   summary line and a row of facts that are true of the place rather than of
   today. */
.gt-dest-hero__summary {
  max-width: var(--gt-w-read);
  margin-top: var(--gt-space-4);
}
.gt-dest-facts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gt-space-2) var(--gt-space-4);
  margin-top: var(--gt-space-5);
  padding: 0;
  list-style: none;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-ink-muted));
}
.gt-dest-facts > li { display: flex; align-items: center; gap: var(--gt-space-2); }
.gt-dest-facts > li + li::before {
  content: "";
  width: 1px;
  height: 12px;
  margin-right: var(--gt-space-4);
  background: currentColor;
  opacity: 0.35;
}


/* --- On-page section navigation -------------------------------------------
   A destination page is long by nature. This is the progressive-depth handle:
   it lets a reader skip to the part they came for instead of scrolling past
   everything else. Rendered only when there are at least two sections. */
.gt-toc {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gt-space-2);
  padding: 0;
  margin: 0;
  list-style: none;
}
.gt-toc a {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 6px 14px;
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-sm);
  background: var(--gt-c-surface, var(--gt-paper-raised));
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--gt-c-text-secondary, var(--gt-ink-muted));
}
.gt-toc a:hover { color: var(--gt-c-text, var(--gt-ink)); border-color: var(--gt-c-border-strong, var(--gt-border-strong)); }


/* --- Editorial body -------------------------------------------------------
   Human prose. Held to a reading measure regardless of how wide the band it
   sits in is, because a destination essay read at 1600px is not read. */
.gt-editorial { max-width: var(--gt-w-read); }
.gt-editorial > * + * { margin-top: var(--gt-space-4); }
.gt-editorial h3 { margin-top: var(--gt-space-7); }
.gt-editorial ul,
.gt-editorial ol { padding-left: var(--gt-space-5); }
.gt-editorial li + li { margin-top: var(--gt-space-2); }
/* Attribution for the editorial layer. §24 of the build brief: human prose,
   AI-assisted approved prose and live intelligence must stay conceptually
   distinct on the page, not just in the database. */
.gt-editorial__byline {
  display: block;
  margin-top: var(--gt-space-5);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
  color: var(--gt-c-text-muted, var(--gt-ink-muted));
}


/* --- Honest empty states --------------------------------------------------
   Ghost Town says what it does not know. This is the visual form of that
   rule, and it is deliberately quiet: an absent reading is information, not
   an error. */
.gt-empty {
  padding: var(--gt-space-6);
  border: 1px dashed var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-md);
  background: var(--gt-c-surface-alt, var(--gt-paper-sunk));
  color: var(--gt-c-text-secondary, var(--gt-ink-muted));
}
.gt-empty__label {
  display: block;
  margin-bottom: var(--gt-space-2);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-muted, var(--gt-ink-muted));
}
.gt-empty p { margin: 0; font-size: var(--gt-fs-body-sm); }


/* --- Advertising slots ----------------------------------------------------
   Ghost Town is commercial from launch, so the placements exist in the
   template from the first page rather than being retrofitted into a finished
   design later.

   Two rules govern them and both are about not damaging the page:

   1. EVERY SLOT RESERVES ITS HEIGHT before anything loads. min-height is set
      per variant below, so an ad arriving late cannot push content down.
      Cumulative Layout Shift from an ad slot should be zero, not small.
   2. A slot with nothing in it renders as a quiet labelled rule, not as a
      grey box pretending to be inventory. There are no fake ads on this site.

   A provider is wired in later by replacing the contents of .gt-ad__inner.
   Nothing outside that element should need to change. */
.gt-ad {
  container-type: inline-size;
  margin: var(--gt-space-8) auto;
  text-align: center;
}
.gt-ad__label {
  display: block;
  margin-bottom: var(--gt-space-2);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-text-muted, var(--gt-ink-muted));
  opacity: 0.7;
}
.gt-ad__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  max-width: 100%;
  border: 1px dashed var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-sm);
  background: var(--gt-c-surface-alt, var(--gt-paper-sunk));
  color: var(--gt-c-text-muted, var(--gt-ink-muted));
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
  overflow: hidden;
}
/* Leaderboard: the below-hero and pre-footer placement. 970x90 desktop,
   collapsing to 320x100 on a phone — both heights reserved up front so the
   swap at the breakpoint is not itself a layout shift. */
.gt-ad--leaderboard .gt-ad__inner { width: 970px; min-height: 90px; }
@media (max-width: 1024px) { .gt-ad--leaderboard .gt-ad__inner { width: 728px; min-height: 90px; } }
@media (max-width: 780px)  { .gt-ad--leaderboard .gt-ad__inner { width: 320px; min-height: 100px; } }
/* In-article: sits between editorial sections. Narrower, and held to the
   reading measure so it does not break the column it interrupts. */
.gt-ad--inline .gt-ad__inner { width: 100%; max-width: var(--gt-w-read); min-height: 250px; }
/* Sidebar: only ever rendered in the wide editorial layout below, and never
   on a phone, where a 300x600 unit would be most of the screen. */
.gt-ad--sidebar { margin: 0; }
.gt-ad--sidebar .gt-ad__inner { width: 300px; min-height: 600px; }
@media (max-width: 1100px) { .gt-ad--sidebar { display: none; } }


/* --- Wide editorial layout ------------------------------------------------
   Article column plus a rail. The rail carries the sidebar ad and any
   at-a-glance panel; below 1100px it stops being a rail and the panels flow
   back into the column in source order, which is why the ad is hidden rather
   than moved. */
.gt-with-rail {
  display: grid;
  gap: var(--gt-space-8);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 1100px) {
  .gt-with-rail { grid-template-columns: minmax(0, 1fr) 300px; align-items: start; }
  .gt-with-rail__rail { position: sticky; top: calc(var(--gt-header-h, 64px) + var(--gt-space-5)); }
}


/* --- Commercial / affiliate placements ------------------------------------
   Reserved locations for lodging, guides, gear and booking links. Empty by
   design: a business appearing in Ghost Town's research is not a commercial
   relationship, and editorial standing must never be inferred from one.
   Nothing here fabricates an endorsement. */
.gt-commerce {
  padding: var(--gt-space-6);
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-left: 3px solid var(--gt-c-warm, var(--gt-rust));
  border-radius: var(--gt-radius-md);
  background: var(--gt-c-surface, var(--gt-paper-raised));
}
.gt-commerce__label {
  display: block;
  margin-bottom: var(--gt-space-2);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-stat-label);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
  color: var(--gt-c-warm, var(--gt-rust));
}
.gt-commerce p { margin: 0; font-size: var(--gt-fs-body-sm); color: var(--gt-c-text-secondary, var(--gt-ink-muted)); }


/* --- Contextual Ask Ghost Town entry point --------------------------------
   The chatbot is one service with one implementation. This is a link that
   carries a question, never a second copy of the chat client. */
.gt-ask-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gt-space-4);
  padding: var(--gt-space-5) var(--gt-space-6);
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-md);
  background: var(--gt-c-surface, var(--gt-paper-raised));
}
.gt-ask-inline__text { flex: 1 1 260px; margin: 0; }
.gt-ask-inline__q {
  display: block;
  font-family: var(--gt-font-display);
  font-size: var(--gt-fs-h4);
  color: var(--gt-c-text, var(--gt-ink));
}
.gt-ask-inline__hint {
  display: block;
  margin-top: var(--gt-space-1);
  font-size: var(--gt-fs-body-sm);
  color: var(--gt-c-text-secondary, var(--gt-ink-muted));
}


/* --- Water navigation -----------------------------------------------------
   Cards for the waters inside a destination. The grade chip shows Ghost
   Town's REPORT COVERAGE for that water. It is never a fishing-quality
   rating, and the label says so rather than relying on the reader to know. */
.gt-water-card__grade {
  display: inline-flex;
  align-items: center;
  gap: var(--gt-space-2);
  padding: 2px 8px;
  border: 1px solid var(--gt-c-border, var(--gt-border));
  border-radius: var(--gt-radius-xs);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gt-c-text-secondary, var(--gt-ink-muted));
}


/* --- Staging review chrome ------------------------------------------------
   Rendered ONLY into the staging build. The production generator never emits
   these elements at all, so there is no CSS-only path by which an internal
   editorial state becomes visible to a reader — the markup is simply absent.
   See web/tools/build/Build-Destinations.ps1. */
.gt-review-bar {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gt-space-3) var(--gt-space-5);
  padding: var(--gt-space-2) var(--gt-space-5);
  background: var(--gt-rust);
  color: #FFFFFF;
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: 0.04em;
}
.gt-review-bar strong { text-transform: uppercase; letter-spacing: var(--gt-ls-label); }
.gt-review-bar a { color: #FFFFFF; }
.gt-state-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 10px;
  border: 1px solid currentColor;
  border-radius: var(--gt-radius-sm);
  font-family: var(--gt-font-mono);
  font-size: var(--gt-fs-meta);
  letter-spacing: var(--gt-ls-label);
  text-transform: uppercase;
}
.gt-state-pill--draft     { color: var(--gt-rust); }
.gt-state-pill--in_review { color: var(--gt-caution); }
.gt-state-pill--published { color: var(--gt-good); }
.gt-state-pill--missing   { color: var(--gt-ink-muted); }
.gt-section--water .gt-state-pill--draft,
.gt-section--panel .gt-state-pill--draft { color: var(--gt-ember); }
.gt-section--water .gt-state-pill--published,
.gt-section--panel .gt-state-pill--published { color: var(--gt-good-dark); }
