/* =============================================================
   Visit Rooibos Country — shared visual layer
   Photos, data graphs, and inline icons. Load AFTER pages.css.

   Everything here is honest: a photo is captioned for what it
   actually shows, a graph plots only sourced figures, and an icon
   is decoration that never carries meaning on its own. All values
   come from tokens in brand/palettes.css — never hardcoded.

   Motion: reveal effects are opt-in via .rv (reveal) and are fully
   disabled under prefers-reduced-motion (see the block at the end).
   ============================================================= */

/* --- photos: a real figure with an honest caption --- */
figure.photo{margin:26px 0;max-width:var(--measure);}
figure.photo img{width:100%;height:auto;border:1px solid var(--line);background:var(--ground-alt);}
figure.photo figcaption{font-family:var(--font-label);font-size:11.5px;line-height:1.55;color:var(--text-soft);padding-top:9px;}
figure.photo figcaption b{color:var(--text);font-weight:600;}
figure.photo figcaption .lic{display:block;margin-top:2px;font-size:10.5px;color:var(--text-soft);}
figure.photo figcaption a{color:var(--structure-deep);}

/* a photo that sits beside text (used on the towns page) */
.figure-pair{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(24px,4vw,48px);align-items:start;}
@media(max-width:860px){.figure-pair{grid-template-columns:1fr;}}
.figure-pair figure.photo{margin:0;}

/* --- data graph: a bar chart drawn in SVG, sourced figures only --- */
.graph{margin:22px 0 6px;max-width:640px;}
.graph .ghead{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin-bottom:14px;}
.graph .ghead .lbl{display:block;}
.graph .ghead .unit{font-family:var(--font-label);font-size:10.5px;color:var(--text-soft);letter-spacing:.02em;}
.graph svg{display:block;width:100%;height:auto;}
.graph .bars{display:flex;align-items:flex-end;gap:clamp(14px,3vw,30px);height:190px;border-bottom:1px solid var(--structure);padding:0 2px;}
.graph .bar{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;height:100%;min-width:0;}
.graph .bar .val{font-family:var(--font-label);font-size:12px;font-weight:600;color:var(--text);margin-bottom:6px;font-variant-numeric:tabular-nums;}
.graph .bar .col{width:100%;max-width:74px;background:var(--structure);border-radius:var(--radius) var(--radius) 0 0;}
.graph .bar.hl .col{background:var(--accent);}
.graph .bar .lbl{font-family:var(--font-label);font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--text-soft);margin-top:8px;text-align:center;}
.graph .gfoot{font-family:var(--font-label);font-size:10.5px;line-height:1.5;color:var(--text-soft);border-top:1px solid var(--line);margin-top:14px;padding-top:9px;}

/* --- inline icons: decoration only, never the carrier of meaning --- */
.icon{display:inline-block;width:1em;height:1em;vertical-align:-0.125em;flex:none;}
.icon--lg{width:1.5em;height:1.5em;}
.icon--struct{color:var(--structure);}
.icon--accent{color:var(--accent);}

/* Rail icons need an explicit size: .icon is 1em, and .rail dt is 9px, so they
   inherited a 9px box and all but vanished. Sized against the label, not the em. */
.rail dt{display:flex;align-items:center;gap:6px;}
.rail dt .icon{width:14px;height:14px;flex:none;color:var(--structure);}
@media(max-width:820px){.rail dt .icon{width:15px;height:15px;}}

/* a small icon + label row (used in the data rail and town cards) */
.iconrow{display:flex;align-items:center;gap:9px;font-family:var(--font-label);font-size:12px;color:var(--text-soft);}
.iconrow svg{color:var(--structure);}

/* --- stat band: four figures, scannable in one glance ------------------
   Pattern borrowed from the SA Rooibos Council homepage, executed in our own
   grammar and with one addition that matters: **every figure carries its
   source**. Theirs carries none, which is why one of their four ("27m cups
   daily") is unusable. Numerals are Fredoka, not a shouting red sans.

   Rebuilt 23 Aug 2026 as CARDS, not a hairline table. Three reasons, in order:
   (1) the brand is rounded and warm (--radius, Fredoka) and the old bare grid
   contradicted it; (2) --line on --paper is too low-contrast to do structural
   work, so the dividers read as smudges rather than separation; (3) one card =
   one claim is the standard pattern for exactly this content, and it makes the
   figure, its meaning and its source obviously one unit.
   The source line is pinned to the card floor with margin-top:auto, so the
   sources align across all four cards no matter how the captions wrap. That
   ragged bottom edge was the single worst thing about the old band.
   ---------------------------------------------------------------------- */
.statband{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px;margin:0 0 26px;}
@media(max-width:860px){.statband{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media(max-width:460px){.statband{grid-template-columns:1fr;}}
.statband .stat{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:24px 22px 18px;min-width:0;display:flex;flex-direction:column;}
.statband .fig{font-family:var(--font-display);font-weight:var(--weight-display);font-size:clamp(32px,4.2vw,44px);
  line-height:1;letter-spacing:var(--track-display);color:var(--ink);display:block;}
.statband .fig sup{font-size:.5em;color:var(--accent);vertical-align:super;margin-left:2px;}
.statband .cap{font-family:var(--font-label);font-size:13px;font-weight:600;line-height:1.45;
  color:var(--ink);margin:11px 0 16px;display:block;}
.statband .src{font-family:var(--font-label);font-size:10.5px;line-height:1.45;color:var(--text-soft);
  margin-top:auto;padding-top:12px;border-top:1px solid var(--line);display:block;}

/* --- fact grid: one sourced claim per tile, photos interleaved ----------
   The Council's "Did You Know?" checkerboard. Same idea, but each tile is a
   single claim traceable to docs/facts.md, and the photo tiles are captioned
   for what they actually show.
   ---------------------------------------------------------------------- */
.factgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:6px 0 4px;}
@media(max-width:1000px){.factgrid{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media(max-width:520px){.factgrid{grid-template-columns:1fr;}}
.factgrid .tile{background:var(--ground-alt);border:1px solid var(--line);padding:20px 20px 17px;
  display:flex;flex-direction:column;justify-content:space-between;min-height:170px;}
.factgrid .tile p{font-family:var(--font-display);font-weight:var(--weight-display);font-size:18px;line-height:1.25;
  margin:0 0 12px;max-width:none;color:var(--ink);letter-spacing:var(--track-display);}
.factgrid .tile .src{font-family:var(--font-label);font-size:10.5px;line-height:1.45;color:var(--text-soft);}
.factgrid figure{margin:0;border:1px solid var(--line);overflow:hidden;display:flex;flex-direction:column;}
.factgrid figure img{width:100%;height:100%;min-height:130px;object-fit:cover;display:block;flex:1;}
.factgrid figcaption{font-family:var(--font-label);font-size:10.5px;line-height:1.45;color:var(--text-soft);
  padding:9px 12px;background:var(--ground);}

/* mobile: keep the stat band and fact tiles readable at arm's length */
@media(max-width:820px){
  .statband .cap{font-size:13px;}
  .statband .src{font-size:11.5px;}
  .factgrid .tile p{font-size:17px;}
  .factgrid .tile .src{font-size:11.5px;}
  .factgrid figcaption{font-size:11.5px;}
}

/* --- season strip -----------------------------------------------------------
   Three non-overlapping periods covering all twelve months, so "which one am I
   in" is never ambiguous. brand/visuals.js marks the current one. It is a
   CALENDAR, not a live feed, and the page says so — we are not reporting
   conditions on the ground, we are stating what time of year does what.

   Cards, matching the stat band above (rebuilt 23 Aug 2026). The "now" card is
   the one thing on this strip that has to be unmistakable, so it gets all three
   signals at once: a warm tint, a full accent border, and the badge — rather
   than the old faint background alone. NOTE: that old tint was
   rgba(125,131,103,.10), grey-green left over from the RETIRED field-guide
   palette, and it clashed with everything around it. Tints belong in
   palettes.css (--tint-structure); do not hardcode another one here.
   --------------------------------------------------------------------------- */
.seasons{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;}
@media(max-width:760px){.seasons{grid-template-columns:1fr;}}
.seasons .season{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  padding:22px;min-width:0;position:relative;}
.seasons .when{font-family:var(--font-label);font-size:10.5px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text-soft);margin-bottom:9px;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;min-height:20px;}
.seasons h3{font-family:var(--font-display);font-weight:var(--weight-display);font-size:21px;line-height:1.2;
  margin:0 0 8px;letter-spacing:var(--track-display);text-transform:var(--uppercase-display);}
.seasons p{font-size:15.5px;line-height:1.55;margin:0;max-width:34ch;}

/* the current period — tint + accent border + badge, all three together */
.seasons .season.now{background:var(--tint-structure);border-color:var(--structure);
  box-shadow:inset 0 0 0 1px var(--structure);}
.seasons .season.now .when{color:var(--structure-deep);}

/* the badge rides the eyebrow line, not the heading. Appending it to a heavy
   uppercase h3 (the old behaviour) left it stranded mid-headline. */
.seasons .badge{font-family:var(--font-label);font-size:9.5px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;background:var(--structure);color:var(--paper);
  padding:4px 10px;border-radius:999px;white-space:nowrap;}
@media(max-width:820px){.seasons p{font-size:16px;}.seasons .when{font-size:11px;}}

/* --- MOTION -------------------------------------------------------------
   Fail-safe by construction. Nothing is hidden until visuals.js adds
   `.motion-on` to <html>, so if the script fails, is blocked, or the browser
   lacks IntersectionObserver, every element simply stays visible.

   (The previous version hid `.rv` unconditionally, which meant a JS failure
   left the page permanently blank. Fixed 22 Aug 2026 — same pattern Visit
   Citrusdal uses in brand/motion.js.)

   transform + opacity only: no layout thrash, cheap on a phone GPU.
   Quiet by design — this is a field guide, not a landing page.
   ------------------------------------------------------------------------ */
.motion-on .rv{opacity:0;transform:translateY(14px);
  transition:opacity .6s cubic-bezier(.2,.7,.2,1),transform .6s cubic-bezier(.2,.7,.2,1);}
.motion-on .rv.in{opacity:1;transform:none;}
.rv--d1{transition-delay:.08s;}
.rv--d2{transition-delay:.16s;}
.rv--d3{transition-delay:.24s;}

/* Graph columns grow from the baseline as the graph comes into view. This
   reveals the data, it never distorts it — the final heights are the sourced
   values and the axis does not move. */
.motion-on .graph.rv .bar .col{transform:scaleY(0);transform-origin:bottom;
  transition:transform .85s cubic-bezier(.2,.7,.2,1);}
.motion-on .graph.rv.in .bar .col{transform:none;}
.motion-on .graph.rv .bar:nth-child(2) .col{transition-delay:.10s;}
.motion-on .graph.rv .bar:nth-child(3) .col{transition-delay:.20s;}
.motion-on .graph.rv .bar:nth-child(4) .col{transition-delay:.30s;}

/* --- hover + focus: small, quiet, never a bounce --- */
nav.top .links a{transition:color .18s ease;}
.onward a{transition:transform .25s cubic-bezier(.2,.7,.2,1),background-color .25s ease;}
.onward a:hover,.onward a:focus-visible{transform:translateX(5px);background:var(--ground-alt);}
figure.photo img{transition:opacity .4s ease;}
.crumbs a,.srcline a{transition:color .18s ease;}

/* Keyboard focus must always be obvious — never remove this. */
a:focus-visible,button:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px;}

/* --- touch: phones have no hover, so give a physical press --- */
.m-press{transform:scale(.985)!important;transition:transform .12s ease!important;}

/* --- honour the user's preference, always. This block must stay last. --- */
@media(prefers-reduced-motion:reduce){
  .motion-on .rv,
  .motion-on .rv.in{opacity:1!important;transform:none!important;transition:none!important;}
  .motion-on .graph.rv .bar .col{transform:none!important;transition:none!important;}
  .onward a,.onward a:hover{transform:none!important;transition:none!important;}
  .m-press{transform:none!important;}
}

/* --- the region map ----------------------------------------------------
   Rendered by brand/region-map.js, which holds the projection, the real
   town coordinates and the reasoning. Colour comes from tokens because the
   SVG is inline; that is the whole reason it is a module and not a file
   dropped in an <img>, which would be cut off from the palette.

   The mount carries real text before the script runs. If the module fails
   the reader still gets the towns and the distance, per the house rule that
   no script may hide content it failed to replace.
   ---------------------------------------------------------------------- */
.mapmount{margin:26px 0 0;max-width:520px;}
.mapmount .fallback{font-family:var(--font-label);font-size:13.5px;line-height:1.6;color:var(--text-soft);
  border:1px solid var(--line);border-radius:var(--radius);padding:18px 20px;background:var(--surface);}
.rmap{margin:0;max-width:none;}
.rmap svg{width:100%;height:auto;display:block;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--radius);}
.rmap figcaption{font-family:var(--font-label);font-size:12px;line-height:1.55;color:var(--text-soft);padding-top:10px;}
.rmap figcaption b{color:var(--text);font-weight:600;}
.rmap figcaption .lic{display:block;margin-top:6px;}
@media(max-width:820px){.rmap figcaption{font-size:12.5px;}.mapmount{max-width:none;}}

/* Map type is in viewBox units, so it shrinks with the drawing: at 390px the
   map renders about 0.56x, which turned 14px notes into 8px on glass. Sized up
   here so the SMALLEST label still lands at ~12.5px on a 360px phone. */
@media(max-width:820px){
  .rmap .rm-name{font-size:30px;}
  .rmap .rm-note{font-size:23px;}
  .rmap .rm-band{font-size:28px;}
  .rmap .rm-sea{font-size:21px;letter-spacing:.12em;}
  .rmap .rm-far .rm-name{font-size:26px;}
}

/* type inside the drawing. Sized against the 620-unit viewBox, so it scales
   with the map and stays legible at 390px. */
.rmap .rm-name{font-family:var(--font-title);font-weight:600;font-size:21px;fill:var(--text);}
.rmap .rm-note{font-family:var(--font-label);font-size:14px;fill:var(--text-soft);}
.rmap .rm-band{font-family:var(--font-title);font-weight:var(--weight-title);font-size:20px;
  fill:var(--structure-deep);text-anchor:middle;opacity:.9;}
.rmap .rm-sea{font-family:var(--font-label);font-size:15px;letter-spacing:.18em;
  text-transform:uppercase;fill:var(--text-soft);opacity:.7;}
.rmap .rm-far .rm-name{font-size:18px;fill:var(--text-soft);}
