/* ==========================================================================
   tgz-ui26.bundle.css — the component kit. Wave W1, 2026-09-07.

   One stylesheet for the six elements in js/tgz-ui26.bundle.js, the page
   shell they sit in, and the handful of patterns a money page is made of
   (photo-led hero, quick-facts strip, CTA row, menu rows, short notes).
   Registered on every route after tgz-flow26 and before the route bundles:
   load order, not !important, settles every cascade — there is none here,
   and there must never be. When a rule in this file loses, the rule reaching
   in is narrowed at its own source.

   Idiom (the one the spa page proved, now shared): no cards. Sections sit on
   one hairline, rows on one hairline, photos on a 6px seam. Inter Tight for
   display and prices, Inter for reading; nothing uppercased. The only action
   colour is the teal. Squared photography; the pill radius is reserved for
   things you press.

   Tokens are page-scoped on .tgzUi and restated as literals for dark mode,
   because on some routes the --tgz-ui-* fallbacks are what actually paint.
   Logical properties everywhere: Arabic mirrors for free.

   Where the boundary is. The gallery dialog and the rail's chrome live in a
   Declarative Shadow DOM root (inc/ui26.php) no page rule can reach.
   Everything a crawler reads is light DOM and is styled here: a shadow
   ::slotted() rule loses to any outer declaration on the same property, so
   this file — not a template — owns the content. Its selectors carry the
   weight the spa page's did (a class plus a type, 0,1,1), and the reach-in
   inventory (scratchpad/cascade_audit.py --reach) shows that is enough:
   nothing legacy targets table cells, tiles or rows above type level. What
   does reach in with a forced override — h1–h3 letter-spacing and the phone
   section padding from tgz-release-4743b and theme-phase407, and every
   dark-mode text colour from theme-phase407 — reaches every page alike and
   is narrowed at its source in the wave that owns it.
   ========================================================================== */

/* --- Elements: block by default; the gallery has no box of its own. ------- */
tgz-tabs,
tgz-table,
tgz-facts,
tgz-mosaic,
tgz-rail { display: block; }
tgz-gallery { display: contents; }

/* --- Tokens --------------------------------------------------------------- */
/* On :root as well as .tgzUi. Shared renderers (trust.php, geo_answer.php)
   emit kit markup on pages whose <main> is not a kit page yet, and a token
   that is undefined there leaves hairlines and ink at their initial values.
   .tgzUi restates them so a kit page still resolves --tgz-ui-* at its own
   level, exactly as before; the page ink stays on .tgzUi alone. */
:root,
.tgzUi {
  --tgz-ui26-bg: var(--tgz-ui-surface, #fffaf1);
  --tgz-ui26-bg-alt: var(--tgz-ui-surface-alt, #f4eadc);
  --tgz-ui26-ink: var(--tgz-ui-text, #172235);
  --tgz-ui26-muted: var(--tgz-ui-muted, #647083);
  --tgz-ui26-muted-band: #596476; /* 5.0:1 on --tgz-ui26-bg-alt; the page muted reads 4.2:1 there */
  --tgz-ui26-line: var(--tgz-ui-line, #e4d4bf);
  --tgz-ui26-line-strong: var(--tgz-ui-line-strong, #c6a77f);
  --tgz-ui26-teal: var(--tgz-ui-teal, #0c7a76);
  --tgz-ui26-teal-ink: #ffffff;
  --tgz-ui26-focus: var(--tgz-ui-focus, #0f8f8a);
  --tgz-ui26-ease: cubic-bezier(.22, 1, .36, 1);
}
.tgzUi { color: var(--tgz-ui26-ink); }
html[data-theme="dark"],
html[data-theme-mode="dark"],
html[data-theme="dark"] .tgzUi,
html[data-theme-mode="dark"] .tgzUi {
  --tgz-ui26-bg: #0d1a22;
  --tgz-ui26-bg-alt: #132530;
  --tgz-ui26-ink: #f7efe3;
  --tgz-ui26-muted: #b7c2c4;
  --tgz-ui26-muted-band: #b7c2c4;
  --tgz-ui26-line: #29404b;
  --tgz-ui26-line-strong: #4b6a73;
  --tgz-ui26-teal: #71d7c2;
  --tgz-ui26-teal-ink: #0b1a22;
  --tgz-ui26-focus: #7fe0d3;
}

/* --- Rhythm: every section sits on one hairline; no boxes. ---------------- */
.tgzUi > .section { padding-block: clamp(1.3rem, 3vw, 2.4rem); }
.tgzUi > .section + .section { border-top: 1px solid var(--tgz-ui26-line); }
.tgzUi > .tgzUiHero { padding-top: clamp(.4rem, 1.5vw, 1.2rem); }
/* A hero that stands before <main> (tgz_ui26_hero 'top': pages whose <main>
   must keep opening on the same block) has its own kit shell, so the
   hairline that would divide it from the next section is drawn on <main>'s
   first section instead. */
.tgzUiTop + main.tgzUi > .section:first-child { border-top: 1px solid var(--tgz-ui26-line); }
.tgzUi h2 {
  margin: 0;
  font: 800 clamp(1.35rem, 2.4vw, 1.7rem)/1.15 "Inter Tight", Inter, system-ui, sans-serif;
  letter-spacing: -.015em;
  color: var(--tgz-ui26-ink);
}
/* A level-3 head (tgz_ui26_head 'level' => 3) opens a block that belongs to the
   section above it - "who each option fits" under "what changes day to day". */
.tgzUi .tgzUiHead h3 {
  margin: 0;
  font: 800 1.1rem/1.2 "Inter Tight", Inter, system-ui, sans-serif;
  letter-spacing: -.01em;
  color: var(--tgz-ui26-ink);
}
.tgzUiLead {
  margin: 6px 0 0;
  max-width: 64ch;
  font: 500 .95rem/1.5 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
.tgzUiFoot {
  margin: 14px 0 0;
  max-width: 80ch;
  font: 500 .82rem/1.5 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
.tgzUi .related { margin-top: 14px; }
/* A list that opens a section shares the section's hairline instead of
   drawing a second one a padding below it - it read as an empty row (W2.1). */
:where(.tgzUi > .section + .section, .tgzUiTop + main.tgzUi > .section:first-child) > tgz-facts:first-child > dl,
:where(.tgzUi > .section + .section, .tgzUiTop + main.tgzUi > .section:first-child) > .tgzUiDeck:first-child { margin-top: 0; border-top: 0; }

/* --- Hero: the photo first, then the promise. ----------------------------- */
.tgzUiHero { display: grid; gap: 18px; }
.tgzUiHero__text { min-width: 0; }
.tgzUiHero h1 {
  margin: 0;
  max-width: 18ch;
  font: 800 clamp(1.9rem, 5.2vw, 3.2rem)/1.04 "Inter Tight", Inter, system-ui, sans-serif;
  letter-spacing: -.025em;
  color: var(--tgz-ui26-ink);
}
.tgzUiHero__lead {
  margin: 14px 0 0;
  max-width: 58ch;
  font: 500 1rem/1.55 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
/* Full-bleed on phones: .container is width:calc(100% - 32px), so 16px is the
   exact gutter. Desktop keeps the photo inside the page column. */
.tgzUiHero__shot {
  order: -1;
  position: relative;
  display: block;
  margin: 0 -16px;
  overflow: hidden;
  background: var(--tgz-ui26-bg-alt);
  cursor: zoom-in;
  text-decoration: none;
}
.tgzUiHero__shot picture { display: block; }
.tgzUiHero__shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform .6s var(--tgz-ui26-ease);
}
/* Ring outside the photo, over the page ground — inset would sit on photo
   pixels whose contrast against the ring nobody can guarantee. */
.tgzUiHero__shot:focus-visible { outline: 3px solid var(--tgz-ui26-focus); outline-offset: 2px; }
.tgzUiHero__hint {
  position: absolute;
  inset-inline-end: 12px;
  bottom: 12px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 11px;
  border-radius: 999px;
  background: rgba(8, 14, 20, .68);
  color: #ffffff;
  font: 700 .76rem/1 Inter, system-ui, sans-serif;
  backdrop-filter: blur(6px);
}
.tgzUiHero__hint svg { width: 15px; height: 15px; }
/* The hero's quiet label: a section head's voice, never a pill. */
.tgzUiHero__kicker {
  display: block;
  margin: 0 0 8px;
  font: 600 .74rem/1.35 Inter, system-ui, sans-serif;
  letter-spacing: .02em;
  color: var(--tgz-ui26-muted);
}
/* A hero photo that opens nothing: __shot's box without the zoom cursor or
   the hover scale. */
.tgzUiHero__media {
  order: -1;
  margin: 0 -16px;
  overflow: hidden;
  background: var(--tgz-ui26-bg-alt);
}
.tgzUiHero__media picture { display: block; }
.tgzUiHero__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* A hero's facts (the recommendation, how a day is planned) sit in the text
   column under the lead - never in the photo's column - and a text-only hero
   keeps them at reading width. */
.tgzUiHero__text > tgz-facts { max-width: 68ch; }

/* Quick facts: a strip of figures on a hairline grid. */
.tgzUiQuick {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  background: var(--tgz-ui26-line);
  border-block: 1px solid var(--tgz-ui26-line);
}
.tgzUiQuick > li { display: grid; gap: 2px; padding: 10px 12px 11px; background: var(--tgz-ui26-bg); }
/* The hairlines are the list's own ground showing through 1px gaps, so an
   empty cell would paint as a solid block of line colour: an odd last item
   spans its row, and from 761px there are exactly as many columns as items. */
.tgzUiQuick > li:last-child:nth-child(odd) { grid-column: 1 / -1; }
.tgzUiQuick b { font: 700 .74rem/1.25 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); }
.tgzUiQuick span { font: 800 1.05rem/1.2 "Inter Tight", Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }

/* The CTA row: the site's primary button first, a ghost second. */
.tgzUiCtas { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.tgzUiCtas > a { width: 100%; justify-content: center; text-align: center; }
/* The site's primary button carries a sheen (core-pre-base .btn.primary::after,
   absolute at inset 0). Unpositioned, the kit's button let it spread over the
   nearest positioned ancestor - a gold veil across the whole hero, photo
   included, and across every section holding a primary action, with a pale
   strip where the full-bleed photo ran past it on phones (W2.1). They are pills
   in both themes like every control beside them: the global .btn radius
   (core-pre-base, tgz-release-4743b; 16px !important in light) stops at the
   kit's rows, which restate the centring, weight and line box those rules
   carried (dark mode's 1.08 line box stops there too). */
.tgzUi .tgzUiCtas > a.btn.primary,
.tgzUi .tgzUiActions > :is(a, button).btn.primary {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  border-radius: 999px;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: 0;
  text-decoration: none;
}
.tgzUi .tgzUiCtas > a.btn.primary { min-height: 48px; padding-block: 12px; }
.tgzUiGhost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 48px;
  padding: 12px 20px;
  border: 1.5px solid var(--tgz-ui26-line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--tgz-ui26-ink);
  font: 700 .95rem/1 Inter, system-ui, sans-serif;
  text-decoration: none;
  transition: border-color .2s, color .2s;
}
.tgzUiGhost svg { width: 18px; height: 18px; flex: none; }
.tgzUiGhost:hover { border-color: var(--tgz-ui26-teal); color: var(--tgz-ui26-teal); }
.tgzUiGhost:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }

@media (hover: hover) { .tgzUiHero__shot:hover img { transform: scale(1.025); } }

@media (min-width: 761px) {
  /* Top-aligned: centring floated the photo 60-85px below the headline on
     every hero whose text runs longer than the photo (layout_gate offset). */
  .tgzUiHero { grid-template-columns: minmax(0, 1fr) minmax(0, 46%); gap: clamp(24px, 4vw, 56px); align-items: start; }
  .tgzUiHero__shot,
  .tgzUiHero__media { order: 0; margin: 0; }
  /* A text-only hero takes the whole row instead of the photo's column. */
  .tgzUiHero__text:only-child { grid-column: 1 / -1; }
  .tgzUiQuick { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
  .tgzUiQuick > li:last-child:nth-child(odd) { grid-column: auto; }
  .tgzUiCtas { flex-direction: row; flex-wrap: wrap; }
  .tgzUiCtas > a { width: auto; min-width: 220px; }
}

/* --- <tgz-mosaic>: one featured frame, the rest on a tight grid. ---------- */
tgz-mosaic > ul {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}
tgz-mosaic > ul > li { margin: 0; min-width: 0; }
.tgzUiTile {
  position: relative;
  display: block;
  height: 100%;
  overflow: hidden;
  background: var(--tgz-ui26-bg-alt);
  cursor: zoom-in;
  text-decoration: none;
}
.tgzUiTile picture { display: block; height: 100%; }
.tgzUiTile img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform .6s var(--tgz-ui26-ease);
}
.tgzUiTile:focus-visible { outline: 3px solid var(--tgz-ui26-focus); outline-offset: 2px; }
.tgzUiTile__cap {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 28px 12px 10px;
  font: 600 .78rem/1.35 Inter, system-ui, sans-serif;
  color: #ffffff;
  text-align: start;
  background: linear-gradient(to top, rgba(8, 14, 20, .74), rgba(8, 14, 20, 0));
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .3s, transform .3s var(--tgz-ui26-ease);
  pointer-events: none;
}
@media (hover: hover) {
  .tgzUiTile:hover img { transform: scale(1.035); }
  .tgzUiTile:hover .tgzUiTile__cap,
  .tgzUiTile:focus-visible .tgzUiTile__cap { opacity: 1; transform: none; }
}
/* Phones: six equal frames, three rows of two. From 620px: the first frame
   is featured at 2×2 and the other five fill the rest — nine cells, three
   clean rows, nothing ragged. */
@media (min-width: 620px) {
  tgz-mosaic > ul { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  tgz-mosaic > ul > li:first-child { grid-column: span 2; grid-row: span 2; }
  tgz-mosaic > ul > li:first-child .tgzUiTile img { aspect-ratio: auto; }
}

/* --- <tgz-gallery>: the dialog is in its shadow root; the document only
   locks scroll while it is open and names the morphing photo. ------------- */
html.is-tgzLb { overflow: hidden; }
/* View Transitions (Chrome/Edge/Safari 18+): the thumbnail morphs into the
   full frame. Other browsers get the dialog's own keyframes; the script decides. */
::view-transition-group(tgz-photo) {
  animation-duration: .42s;
  animation-timing-function: cubic-bezier(.22, 1, .36, 1);
}
::view-transition-old(tgz-photo),
::view-transition-new(tgz-photo) {
  height: 100%;
  object-fit: cover;
  animation-duration: .42s;
}

/* --- <tgz-tabs>: every panel is in the HTML; the tab only picks which one
   is showing, and each #id still deep-links. ------------------------------- */
.tgzUiTablist {
  display: flex;
  gap: 6px;
  margin: 16px 0 0;
  padding: 0 0 4px;
  overflow-x: auto;
  scrollbar-width: none;
}
.tgzUiTablist::-webkit-scrollbar { display: none; }
.tgzUiTablist a {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 9px 15px;
  border: 1px solid var(--tgz-ui26-line);
  border-radius: 999px;
  background: var(--tgz-ui26-bg);
  color: var(--tgz-ui26-ink);
  font: 700 .86rem/1 Inter, system-ui, sans-serif;
  text-decoration: none;
  white-space: nowrap;
  transition: background .2s, color .2s, border-color .2s;
}
.tgzUiTablist a:hover { border-color: var(--tgz-ui26-line-strong); }
.tgzUiTablist a[aria-selected="true"] { background: var(--tgz-ui26-ink); border-color: var(--tgz-ui26-ink); color: var(--tgz-ui26-bg); }
.tgzUiTablist a:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }
tgz-tabs.is-enhanced [data-tgz-panel][hidden] { display: none; }
.tgzUiPanel { margin-top: 16px; scroll-margin-top: 84px; }
.tgzUiPanel > h3 {
  margin: 0;
  font: 800 1.05rem/1.25 "Inter Tight", Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-ink);
}
/* Once tabs are live the selected chip already says the panel's name. */
tgz-tabs.is-enhanced .tgzUiPanel > h3 {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.tgzUiPanel > p {
  margin: 4px 0 0;
  max-width: 72ch;
  font: 500 .88rem/1.45 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
tgz-tabs.is-enhanced .tgzUiPanel > p { margin-top: 0; }

/* --- <tgz-table>: the hairline price table. The global table{min-width},
   th{background} and th,td{text-align:left} are each restated on the kit's
   own scope. When the table has to scroll, the element becomes a labelled,
   focusable region (js) and the ring says so. ------------------------------ */
tgz-table { margin-top: 10px; overflow-x: auto; }
tgz-table:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }
tgz-table > table {
  width: 100%;
  min-width: 0;
  border-collapse: collapse;
  background: transparent;
  font-family: Inter, system-ui, sans-serif;
}
tgz-table table th,
tgz-table table td {
  background: transparent;
  text-align: start;
  text-transform: none;
  letter-spacing: 0;
  /* Cells meet on their first line: middle alignment floated a one-line
     label beside a three-line note (498 rows, layout_gate row, W2.1). */
  vertical-align: baseline;
}
tgz-table thead th {
  vertical-align: bottom;
  padding: 0 8px 8px;
  border-bottom: 1px solid var(--tgz-ui26-line-strong);
  font: 600 .72rem/1.2 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
tgz-table tbody th,
tgz-table tbody td { padding: 11px 8px; border-bottom: 1px solid var(--tgz-ui26-line); }
tgz-table th:first-child,
tgz-table td:first-child { padding-inline-start: 2px; }
tgz-table th:last-child,
tgz-table td:last-child { padding-inline-end: 2px; }
tgz-table tbody th[scope="row"] { font: 600 .92rem/1.3 Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
/* A note cell reads at the row label's size; at 320px the page's body size
   made it the largest text in the row (W2.1). */
tgz-table tbody td { font: 500 .9rem/1.45 Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
/* Duration, price and the action cluster at the end of the row, menu-style,
   so a wide desktop table does not leave "30 min" floating mid-page. */
tgz-table thead th.tgzUiEnd { text-align: end; }
td.tgzUiDur { text-align: end; }
/* W2 decided the price column once, for every kit table: at the end of the
   row, under its end-aligned heading (.tgzUiPrice below). W1 had kept the spa
   page's accidental start alignment for its pixel-identical gate; the hammam
   price column now lines up with its own heading like every other. */
.tgzUiDur { font: 500 .8rem/1.2 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); white-space: nowrap; }
.tgzUiPrice {
  font: 800 .98rem/1.2 "Inter Tight", Inter, system-ui, sans-serif;
  font-variant-numeric: tabular-nums;
  color: var(--tgz-ui26-ink);
  white-space: nowrap;
  text-align: end;
}
/* A price cell may carry its unit and a local-currency hint, each a line of
   its own under the figure and never broken: "per person" used to split in
   two at 320px, and "(≈ 3 810 DH)" inside the number. A prefix ("From")
   stays on the figure's line. */
.tgzUiPrice > .tgzUiUnit { display: block; margin-top: 3px; }
.tgzUiPrice > small { font: 500 .74rem/1.2 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); }
.tgzUiAct { width: 1%; text-align: end; }
.tgzUiAct a,
.tgzUiRow__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--tgz-ui26-teal);
  color: var(--tgz-ui26-teal-ink);
  text-decoration: none;
  white-space: nowrap;
  transition: filter .15s, transform .15s;
}
.tgzUiAct a { min-height: 34px; min-width: 56px; padding: 7px 13px; font: 800 .78rem/1 Inter, system-ui, sans-serif; }
.tgzUiAct a:hover,
.tgzUiRow__cta:hover { filter: brightness(1.08); }
.tgzUiAct a:active,
.tgzUiRow__cta:active { transform: scale(.97); }
.tgzUiAct a:focus-visible,
.tgzUiRow__cta:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }
@media (max-width: 359px) {
  tgz-table tbody th,
  tgz-table tbody td { padding: 9px 5px; }
  .tgzUiAct a { min-width: 46px; padding: 7px 9px; }
}

/* --- Rows: menu rows, price column at the end. ---------------------------- */
.tgzUiRows { display: grid; margin-top: 14px; border-top: 1px solid var(--tgz-ui26-line); }
.tgzUiRow { display: grid; gap: 8px; padding: 14px 2px; border-bottom: 1px solid var(--tgz-ui26-line); }
.tgzUiRow__main { display: grid; gap: 3px; min-width: 0; }
.tgzUiRow__main b { font: 800 1rem/1.25 "Inter Tight", Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
.tgzUi .tgzUiRow__main b a { color: inherit; text-decoration: none; }
.tgzUi .tgzUiRow__main b a:hover { color: var(--tgz-ui26-teal); }
.tgzUiRow__main b a:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }
.tgzUiRow__main small { max-width: 60ch; font: 500 .86rem/1.45 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); }
.tgzUiRow__meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.tgzUiRow__meta .tgzUiPrice { font-size: 1.15rem; }
.tgzUiUnit { font: 500 .78rem/1.2 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); }
.tgzUiRow__cta { width: max-content; min-height: 40px; padding: 9px 16px; font: 800 .84rem/1 Inter, system-ui, sans-serif; }
@media (min-width: 761px) {
  .tgzUiRow { grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 24px; }
  .tgzUiRow__meta { justify-content: flex-end; }
}

/* The offer: the site's one product card — photo, name, live price, what is
   included, one control. It replaces oePkgCard, v30StepCard, v29Route,
   tgzStayCard and the includesGrid boxes. Still no card chrome: a hairline
   under each offer, the photo on the 6px seam, the price set in figures. */
.tgzUiOffers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(16px, 2.4vw, 28px);
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}
.tgzUiOffer {
  display: grid;
  align-content: start;
  gap: 10px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--tgz-ui26-line);
}
.tgzUiOffer picture { display: block; overflow: hidden; background: var(--tgz-ui26-bg-alt); }
.tgzUiOffer img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}
.tgzUiOffer__head { display: grid; gap: 3px; }
.tgzUiOffer__head :is(b, h3, h4) {
  margin: 0;
  font: 800 1.02rem/1.25 "Inter Tight", Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-ink);
}
.tgzUiOffer__price { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 8px; }
.tgzUiOffer__price .tgzUiPrice { font-size: 1.18rem; }
.tgzUiOffer__incl { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; }
.tgzUiOffer__incl > li {
  font: 500 .86rem/1.45 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
.tgzUiOffer .tgzUiRow__cta { width: 100%; justify-content: center; }
@media (min-width: 561px) { .tgzUiOffer .tgzUiRow__cta { width: max-content; } }

/* --- <tgz-facts>: facts one line each; one column per fact on desktop. --- */
tgz-facts > dl { display: grid; margin: 14px 0 0; padding: 0; border-top: 1px solid var(--tgz-ui26-line); }
.tgzUiFact { display: grid; gap: 3px; padding: 11px 2px; border-bottom: 1px solid var(--tgz-ui26-line); }
.tgzUiFact dt { margin: 0; font: 700 .76rem/1.25 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); }
.tgzUiFact dd { margin: 0; font: 500 .9rem/1.45 Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
.tgzUiFact dd > span { display: block; }
/* A fact's figure (tgz_ui26_facts 'figure') is the one thing to read first;
   the lines under it are its note. */
.tgzUiFact dd > strong { display: block; font: 800 1.02rem/1.25 "Inter Tight", Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
.tgzUiFact dd > strong ~ span { margin-top: 2px; color: var(--tgz-ui26-muted); }
@media (min-width: 761px) {
  tgz-facts > dl { grid-template-columns: repeat(var(--tgz-ui26-cols, 4), minmax(0, 1fr)); gap: 0 24px; border-bottom: 1px solid var(--tgz-ui26-line); }
  .tgzUiFact { padding: 14px 0; border-bottom: 0; }
}

/* --- Notes: short notes, three across on desktop unless --tgz-ui26-cols. -- */
.tgzUiNotes { display: grid; gap: 14px; margin-top: 14px; }
.tgzUiNote { padding-top: 12px; border-top: 1px solid var(--tgz-ui26-line); }
/* A note may carry an h2 (the town pages keep their outline) or an h3, under an optional quiet label. */
.tgzUiNote > span { display: block; margin-bottom: 3px; font: 600 .8rem/1.3 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); }
.tgzUiNote :is(h2, h3) { margin: 0; font: 800 .98rem/1.25 "Inter Tight", Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
.tgzUiNote p { margin: 5px 0 0; font: 500 .9rem/1.5 Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
@media (min-width: 761px) { .tgzUiNotes { grid-template-columns: repeat(var(--tgz-ui26-cols, 3), minmax(0, 1fr)); gap: 0 28px; } }

/* --- <tgz-rail>: the frame is in the shadow root; the items are light DOM
   and a shadow ::slotted() rule cannot be trusted to win, so the item
   contract is stated here too. -------------------------------------------- */
tgz-rail > :not(template) { flex: 0 0 auto; scroll-snap-align: start; }

/* --- W2 (2026-09-09): the four patterns every money page repeats. ---------
   Before this wave the same four things were written a dozen ways:
   landingMiniCard, v30PointCard, tgzStayMoneyRoutes, tgzCommercialIntentGrid,
   tgzDurationCards / LinkDeck / SynergyGrid / LocationStrip, routeRibbon,
   v29Route, .related and .content. They are one deck, one chip line, one
   action row and one section head from here on.
   -------------------------------------------------------------------------- */

/* Section head: a quiet label, the heading, the lead. The three eyebrow PILL
   styles this replaces are gone - a label is a label, not a control. */
.tgzUiHead { display: grid; gap: 4px; }
.tgzUiHead > span {
  font: 600 .74rem/1.35 Inter, system-ui, sans-serif;
  letter-spacing: .02em;
  color: var(--tgz-ui26-muted);
}
.tgzUiHead > p {
  margin: 4px 0 0;
  max-width: 68ch;
  font: 500 .95rem/1.5 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}

/* The deck: a list of links, one per line, on hairlines. Never a card.
   --tgz-ui26-cols is how many columns it takes from 761px up. */
.tgzUiDeck {
  display: grid;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--tgz-ui26-line);
}
.tgzUiDeck > li { display: contents; }
.tgzUiDeck > :is(a, div, li > a, li > div) {
  display: grid;
  align-content: start;
  gap: 3px;
  padding: 12px 2px;
  border-bottom: 1px solid var(--tgz-ui26-line);
  text-decoration: none;
  transition: background .2s;
}
.tgzUiDeck b {
  font: 700 .95rem/1.3 "Inter Tight", Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-ink);
}
.tgzUiDeck :is(span, small, p) {
  margin: 0;
  font: 500 .86rem/1.45 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
.tgzUiDeck a:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: -2px; }
.tgzUiDeck a[aria-current="page"] b { color: var(--tgz-ui26-teal); }
@media (hover: hover) {
  .tgzUiDeck a:hover b { color: var(--tgz-ui26-teal); }
}
@media (min-width: 761px) {
  .tgzUiDeck {
    grid-template-columns: repeat(var(--tgz-ui26-cols, 2), minmax(0, 1fr));
    column-gap: clamp(18px, 2.4vw, 32px);
  }
}

/* Chips: FACTS, set as text. The defect this fixes - /surf-camps/ at 390px
   showed seven identical-looking buttons of which four were not buttons
   ("Reviewed quote first", "No card charged here"). A control is a control;
   a fact is a line of text, and now it looks like one. */
/* W2.1: every fact carries its own marker, so a wrapped line starts on the
   same edge as the first (the separator before each later fact indented
   every wrapped line by 18px), and a phone reads one fact per line. */
.tgzUiChips {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}
.tgzUiChips > li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font: 500 .84rem/1.5 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
.tgzUiChips > li::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  margin-top: calc(.75em - 3px);
  border-radius: 50%;
  background: var(--tgz-ui26-line-strong);
}
@media (min-width: 561px) { .tgzUiChips { flex-direction: row; flex-wrap: wrap; gap: 4px 20px; } }

/* The action row: the site's primary button, then ghosts. One action colour,
   and every control here is genuinely a control. */
.tgzUiActions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.tgzUiActions > :is(a, button) { flex: 1 1 auto; }
.tgzUi .tgzUiActions > :is(a, button).btn.primary { min-height: 44px; padding-block: 11px; }
.tgzUiActions > .tgzUiGhost { min-height: 44px; padding: 11px 18px; font-size: .88rem; }
@media (min-width: 561px) { .tgzUiActions > :is(a, button) { flex: 0 0 auto; } }

/* Media deck: photo cards on the 6px seam, squared, price at the end of the
   title line. Replaces routeRibbon / v29Route / phase21MediaGrid. */
.tgzUiMediaDeck {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 6px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}
.tgzUiMediaDeck > li { display: contents; }
.tgzUiShot {
  display: grid;
  align-content: start;
  gap: 8px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--tgz-ui26-line);
  text-decoration: none;
}
.tgzUiShot picture { display: block; overflow: hidden; background: var(--tgz-ui26-bg-alt); }
.tgzUiShot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform .6s var(--tgz-ui26-ease);
}
.tgzUiShot__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.tgzUiShot__top strong {
  font: 700 .98rem/1.25 "Inter Tight", Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-ink);
}
.tgzUiShot p {
  margin: 0;
  font: 500 .86rem/1.45 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}
.tgzUiShot:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }
@media (hover: hover) {
  .tgzUiShot:hover img { transform: scale(1.03); }
  .tgzUiShot:hover .tgzUiShot__top strong { color: var(--tgz-ui26-teal); }
}

/* --- FAQ: questions on hairlines, like every other list here (W2.1). The
   boxed accordion - a card per question, and in dark mode a second box inside
   it - was the last card on a kit page. Its reach-in !important rules
   (tgz-release-4743b's global details/summary, theme-phase407's dark FAQ lock,
   core-tail's dark border colour) stop at .tgzUi .faq at their source. ------ */
.tgzUi .faq {
  display: grid;
  gap: 0;
  margin-top: 14px;
  border-top: 1px solid var(--tgz-ui26-line);
}
.tgzUi .faq details {
  margin: 0;
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--tgz-ui26-line);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.tgzUi .faq summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  min-height: 44px;
  padding: 13px 2px;
  border-radius: 0;
  list-style: none;
  cursor: pointer;
  font: 700 .98rem/1.4 "Inter Tight", Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-ink);
}
.tgzUi .faq summary::-webkit-details-marker { display: none; }
.tgzUi .faq summary::after {
  content: "+";
  flex: none;
  width: 1.2em;
  font: 500 1.3rem/1.05 Inter, system-ui, sans-serif;
  text-align: center;
  color: var(--tgz-ui26-teal);
}
.tgzUi .faq details[open] > summary::after { content: "\2212"; }
.tgzUi .faq summary:focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }
.tgzUi .faq details > p {
  margin: 0;
  padding: 0 2px 14px;
  max-width: 72ch;
  font: 500 .92rem/1.55 Inter, system-ui, sans-serif;
  color: var(--tgz-ui26-muted);
}

/* --- Anchor colour, page-scoped. theme-phase407 paints every dark-mode link
   (html[data-theme="dark"] body :where(a) — specificity 0,1,2) and would
   outrank the single-class rules above; these carry the page's own weight.
   Its two !important mint rules are carved out at the source (.tgzUi a). --- */
.tgzUi .tgzUiTablist a { color: var(--tgz-ui26-ink); }
.tgzUi .tgzUiTablist a[aria-selected="true"] { color: var(--tgz-ui26-bg); }
.tgzUi .tgzUiAct a,
.tgzUi .tgzUiRow__cta { color: var(--tgz-ui26-teal-ink); }
.tgzUi .tgzUiDeck a,
.tgzUi .tgzUiShot { color: var(--tgz-ui26-ink); }
.tgzUi .tgzUiGhost { color: var(--tgz-ui26-ink); }
.tgzUi .tgzUiGhost:hover { color: var(--tgz-ui26-teal); }

/* --- Reduced motion: nothing moves; the lightbox simply appears. ---------- */
@media (prefers-reduced-motion: reduce) {
  .tgzUiHero__shot img,
  .tgzUiTile img,
  .tgzUiTile__cap,
  .tgzUiShot img,
  .tgzUiDeck > :is(a, div),
  .tgzUiGhost,
  .tgzUiTablist a,
  .tgzUiAct a,
  .tgzUiRow__cta { transition: none; }
  .tgzUiHero__shot:hover img,
  .tgzUiTile:hover img,
  .tgzUiShot:hover img { transform: none; }
  ::view-transition-group(tgz-photo),
  ::view-transition-old(tgz-photo),
  ::view-transition-new(tgz-photo) { animation: none; }
}

/* --- Form fields (W4): /start/, /contact/, the /money/ converter. --------- */
.tgzUi .tgzUiForm { display: grid; gap: 12px; margin-top: 14px; }
.tgzUi .tgzUiForm__row { display: grid; gap: 12px; }
@media (min-width: 761px) { .tgzUi .tgzUiForm__row { grid-template-columns: repeat(var(--tgz-ui26-cols, 2), minmax(0, 1fr)); } }
.tgzUi .tgzUiForm label { display: grid; gap: 4px; font: 600 .82rem/1.3 Inter, system-ui, sans-serif; color: var(--tgz-ui26-muted); }
.tgzUi .tgzUiForm :is(input, select, textarea) { width: 100%; min-height: 44px; padding: 9px 12px; border: 1px solid var(--tgz-ui26-line-strong); border-radius: 10px; background: var(--tgz-ui26-bg); color: var(--tgz-ui26-ink); font: 500 .95rem/1.4 Inter, system-ui, sans-serif; }
.tgzUi .tgzUiForm textarea { min-height: 120px; resize: vertical; }
.tgzUi .tgzUiForm :is(input, select, textarea):focus-visible { outline: 2px solid var(--tgz-ui26-focus); outline-offset: 2px; }
.tgzUi .tgzUiForm output { display: block; min-height: 1.5em; font: 800 1.15rem/1.3 "Inter Tight", Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }
.tgzUi .tgzUiForm .tgzUiActions { margin-top: 2px; }
.tgzUi .tgzUiActions > button.btn.primary { appearance: none; border: 0; cursor: pointer; font: inherit; }
.tgzUi .tgzUiMessage { margin: 0 0 4px; padding: 10px 12px; border: 1px solid var(--tgz-ui26-line-strong); border-radius: 10px; font: 600 .9rem/1.4 Inter, system-ui, sans-serif; color: var(--tgz-ui26-ink); }

/* --- Phone rhythm (W4): the kit owns its section padding at every width.
   This is the value theme-phase407 used to force onto every main section with
   !important; that rule no longer reaches .tgzUi, and nothing moved. ------- */
@media (max-width: 780px) { main.tgzUi > .section { padding-block: clamp(8px, 3vw, 16px); } }

/* --- Card rails (W4c): the media deck's and the storefront's cards inside
   <tgz-rail>. On a phone one snap carousel (the rail's own track, buttons and
   edge fades); from 761px the same cards sit on a grid - the shadow track is
   restyled through ::part(track), the buttons never appear. -------------- */
tgz-rail.tgzUiRail--cards > .tgzUiShot { width: min(78vw, 300px); }
tgz-rail.tgzUiRail--cards > .tgzUiOffer { width: min(82vw, 320px); }
tgz-rail.tgzUiRail--cards > .tgzUiOffer img { aspect-ratio: 3 / 2; }
@media (min-width: 761px) {
  /* The same auto-fit columns the kit's own grids use, so a column is never
     narrower than a card: at 820px the German titles pushed four fixed
     columns 63px past the screen (layout_gate, W4c). */
  tgz-rail.tgzUiRail--cards::part(track) { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: 6px; overflow: visible; mask-image: none; -webkit-mask-image: none; }
  tgz-rail.tgzUiRail--offers::part(track) { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: clamp(16px, 2.4vw, 28px); }
  tgz-rail.tgzUiRail--cards::part(btn) { display: none; }
  tgz-rail.tgzUiRail--cards > .tgzUiShot,
  tgz-rail.tgzUiRail--cards > .tgzUiOffer { width: auto; min-width: 0; }
}

/* --- Page variants (W4d): opt-in structure for a page that needs more than
   one column of hairlines (the homepage, owner 2026-09-13). Kit-owned. ----- */
/* Dense: less air between blocks at every width. */
.tgzUi.tgzUi--dense > .section { padding-block: clamp(.9rem, 2.2vw, 1.6rem); }
/* Band: a tinted full-bleed strip behind a section - furniture, not a card. */
.tgzUi > .section.tgzUiBand { --tgz-ui26-muted: var(--tgz-ui26-muted-band); background: var(--tgz-ui26-bg-alt); box-shadow: 0 0 0 100vmax var(--tgz-ui26-bg-alt); clip-path: inset(0 -100vmax); border-top: 0; }
.tgzUi > .section.tgzUiBand + .section { border-top: 0; }
/* Split: from 1024px the head takes a left column and the body sits beside it,
   so a wide screen is used across rather than down. */
@media (min-width: 1024px) {
  .tgzUi > .section.tgzUiSplit { display: grid; grid-template-columns: minmax(200px, 280px) minmax(0, 1fr); column-gap: clamp(28px, 4vw, 64px); align-items: start; }
  .tgzUi > .section.tgzUiSplit > .tgzUiHead { position: sticky; top: 92px; }
  .tgzUi > .section.tgzUiSplit > .tgzUiHead p { max-width: none; }
  .tgzUi > .section.tgzUiSplit > .tgzUiHead + * { margin-top: 0; }
  .tgzUiSplit > .tgzUiHead + tgz-facts > dl,
  .tgzUiSplit > .tgzUiHead + .tgzUiDeck { margin-top: 0; border-top: 0; }
}
/* Tall hero: the photo fills the hero's height beside the text. */
@media (min-width: 761px) {
  .tgzUiHero--tall { align-items: stretch; }
  .tgzUiHero--tall .tgzUiHero__media { display: grid; }
  .tgzUiHero--tall .tgzUiHero__media picture { height: 100%; }
  .tgzUiHero--tall .tgzUiHero__media img { height: 100%; min-height: 100%; aspect-ratio: auto; }
}
