/* ===================================================================
   travee+ landing — DESIGN A, "Daylight".
   White paper, one cyan, ink type. Everything is scoped to .tv so the
   signed-in app's style.css is untouched: this file must never change
   how /app looks. `.hidden` stays !important in style.css, which is
   what keeps the login / register / OTP toggling working underneath.
   A second treatment of the same content lives at /landing-b.
   =================================================================== */
html { scroll-behavior: smooth; scroll-padding-top: 92px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto } }

/* The palette, separated from the page styling below it.
 *
 * .tv-nav and .tv-foot carry it too because the masthead and the footer are
 * shared with the app shell's logged-out branch (partials/masthead.php,
 * partials/footer.php), whose <body> is not .tv — without this every colour in
 * them resolved to nothing there. Only the variables are shared: the
 * background, text colour and font below stay on .tv, so including the chrome
 * on a catalogue page does not restyle the catalogue. */
.tv, .tv-nav, .tv-foot {
  --cyan:    #25A8CB;
  --cyan-d:  #17819F;
  --cyan-w:  #E8F6FA;
  --ink:     #0B1015;
  --ink-2:   #4C5860;
  --ink-3:   #7B888F;
  --paper:   #FFFFFF;
  --paper-2: #F6F9FA;
  --line:    #E3EAEE;
  --line-2:  #D3DEE3;
}
/* The chrome keeps the public site's face on a page set in the app's Poppins. */
.tv-nav, .tv-foot { font-family: 'Outfit', ui-sans-serif, system-ui, sans-serif; }
.tv {
  background: var(--paper);
  color: var(--ink);
  font-family: 'Outfit', ui-sans-serif, system-ui, sans-serif;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
.tv ::selection { background: var(--cyan); color: #fff; }
/* Border-box and no default margin, once, for everything this sheet styles.
 * Every width in here assumes it — .tv-btn { width: 100% } carries its own
 * padding, so under content-box a full-width button on a phone is 44px wider
 * than the gutter it is supposed to sit inside. The front door used to inherit
 * the reset from style.css; it no longer loads it, and the other public pages
 * never loaded it at all. Scoped to the public chrome, so /app is untouched
 * (style.css resets it there already, to the same value). */
.tv, .tv *, .tv *::before, .tv *::after,
.tv-nav, .tv-nav *, .tv-foot, .tv-foot * { box-sizing: border-box; }
body.tv { margin: 0; }
/* A fixed gutter rather than a percentage: 92vw on a 375px phone leaves 15px
   of margin, which reads as text jammed against the bezel. */
.tv-wrap { width: min(1180px, 100% - 44px); margin-inline: auto; }
@media (max-width: 480px) { .tv-wrap { width: calc(100% - 36px); } }
.tv-serif { font-family: 'Instrument Serif', Georgia, serif; font-weight: 400; }

/* ---- the loading screen ---------------------------------------- */
/* Removed on window.load, and unconditionally after 2.2s. A splash that
   can outlive a slow font request is a splash that locks people out. */
#boot { display: none }
.js #boot {
  position: fixed; inset: 0; z-index: 9999; display: grid; place-items: center;
  background: #fff; transition: opacity .55s ease, visibility .55s;
}
#boot.gone { opacity: 0; visibility: hidden; pointer-events: none; }
.boot-in { display: grid; justify-items: center; gap: 26px; }
.boot-pin { width: 76px; height: 76px; animation: boot-drop .9s cubic-bezier(.2,.9,.25,1) both; }
@keyframes boot-drop {
  0%   { transform: translateY(-26px) scale(.86); opacity: 0 }
  60%  { transform: translateY(4px)   scale(1.02); opacity: 1 }
  100% { transform: none; opacity: 1 }
}
/* The ground ripple lands as the pin does — it is what makes it read as
   a pin dropping onto a map rather than a logo fading in. */
.boot-ring {
  width: 74px; height: 12px; border-radius: 50%; margin-top: -8px;
  border: 1.5px solid var(--cyan); opacity: 0;
  animation: boot-ring 1.5s .55s ease-out infinite;
}
@keyframes boot-ring {
  0%   { transform: scale(.3); opacity: .7 }
  100% { transform: scale(1.5); opacity: 0 }
}
.boot-word {
  font-size: 1.5rem; font-weight: 700; font-style: italic; letter-spacing: -.03em;
  color: var(--cyan); animation: boot-fade .7s .25s both;
}
.boot-word span { color: var(--ink); font-style: normal; font-weight: 300; letter-spacing: 0; }
@keyframes boot-fade { from { opacity: 0; transform: translateY(8px) } to { opacity: 1 } }
.boot-bar { width: 168px; height: 3px; border-radius: 99px; background: var(--line); overflow: hidden; }
.boot-bar i { display: block; height: 100%; width: 34%; border-radius: 99px; background: var(--cyan); animation: boot-slide 1.15s ease-in-out infinite; }
@keyframes boot-slide { 0% { transform: translateX(-110%) } 100% { transform: translateX(330%) } }
@media (prefers-reduced-motion: reduce) {
  .boot-pin, .boot-word, .boot-ring, .boot-bar i { animation: none }
}

/* ---- masthead --------------------------------------------------- */
.tv-nav {
  position: sticky; top: 0; z-index: 60;
  /* the drop panel is absolute against this, full-bleed rather than inside the
     content column — a menu that stops at the gutter looks like a mistake */ background: rgba(255,255,255,.86);
  backdrop-filter: saturate(180%) blur(14px); border-bottom: 1px solid transparent;
  transition: border-color .2s;
}
.tv-nav.stuck { border-bottom-color: var(--line); box-shadow: 0 10px 30px -24px rgba(11,16,21,.55); }
.tv-nav .tv-wrap { display: flex; align-items: center; gap: 22px; height: 70px; }
.tv-mark { display: flex; align-items: center; gap: 9px; text-decoration: none; }
.tv-mark img { width: 30px; height: 30px; }
.tv-mark b {
  font-size: 1.28rem; font-weight: 700; font-style: italic; letter-spacing: -.035em; color: var(--cyan);
}
.tv-nav nav { margin-left: auto; display: flex; align-items: center; gap: 28px; }
/* Log in and the burger, outside #tvMenu so neither ever collapses into it.
   Log in used to be the menu's last item, which on a phone put the one thing a
   returning user came for two taps away behind the burger. */
.tv-actions { display: flex; align-items: center; gap: 10px; margin-left: 18px; flex: none; }
.tv-nav nav a {
  color: var(--ink-2); text-decoration: none; font-size: .93rem; font-weight: 500;
  position: relative; padding: 4px 0;
}
.tv-nav nav a::after {
  content: ''; position: absolute; left: 0; right: 100%; bottom: 0; height: 1.5px;
  background: var(--cyan); transition: right .22s;
}
.tv-nav nav a:hover { color: var(--ink); }
.tv-nav nav a[aria-current] { color: var(--cyan-d); }
.tv-nav nav a:hover::after { right: 0; }

/* ---- mobile masthead -------------------------------------------- */
/* Below 860px the links move into a panel that drops from the bar. Hiding
   them instead (which is what tv-hide-sm used to do) left a phone with a
   masthead that could not reach half the site. */
.tv-burger {
  display: none; width: 42px; height: 42px; flex: none;
  align-items: center; justify-content: center;
  border: 1.5px solid var(--line-2); border-radius: 11px; background: #fff;
  color: var(--ink); font-size: 1.02rem; cursor: pointer; transition: .18s;
}
.tv-burger:hover { border-color: var(--ink); }
.tv-burger .fa-xmark { display: none; }
.tv-nav.open .tv-burger .fa-xmark { display: block; }
.tv-nav.open .tv-burger .fa-bars  { display: none; }

@media (max-width: 860px) {
  .tv-burger { display: inline-flex; }
  /* The menu leaves the flow below this width, so the actions take the gap. */
  .tv-actions { margin-left: auto; }
  .tv-nav .tv-wrap { height: 62px; }
  .tv-nav nav {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: #fff; border-bottom: 1px solid var(--line);
    padding: 6px 4vw 18px;
    box-shadow: 0 22px 40px -26px rgba(11,16,21,.5);
    /* Collapsed by height rather than display:none, so it can animate and so
       the links stay in the accessibility tree while it is opening. */
    max-height: 0; overflow: hidden; visibility: hidden;
    transition: max-height .3s cubic-bezier(.2,.8,.2,1), visibility .3s;
  }
  .tv-nav.open nav { max-height: 70vh; overflow-y: auto; visibility: visible; }
  /* The panel's contents settle a beat after it opens. A list that is fully
     drawn before the panel finishes moving reads as a jump, not a menu. */
  .tv-nav nav > * { opacity: 0; transform: translateY(-6px); transition: opacity .26s ease, transform .26s ease; }
  .tv-nav.open nav > * { opacity: 1; transform: none; transition-delay: .09s; }
  .tv-nav nav a {
    padding: 14px 4px; font-size: 1rem; border-bottom: 1px solid var(--line);
  }
  .tv-nav nav a::after { display: none; }
  .tv-nav nav a:last-of-type { border-bottom: 0; }
  .tv-nav nav .tv-btn { margin-top: 14px; justify-content: center; width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .tv-nav nav, .tv-nav nav > * { transition: none }
  .tv-nav nav > * { opacity: 1; transform: none }
}

/* ---- buttons ---------------------------------------------------- */
.tv-btn {
  display: inline-flex; align-items: center; gap: 9px; border-radius: 999px;
  font: inherit; font-size: .95rem; font-weight: 600; padding: 12px 24px;
  cursor: pointer; border: 1.5px solid transparent; text-decoration: none;
  transition: transform .16s, box-shadow .2s, background .2s, color .2s;
}
.tv-btn:active { transform: translateY(1px); }
.tv-solid { background: var(--cyan); color: #fff; box-shadow: 0 8px 22px -10px rgba(37,168,203,.9); }
.tv-solid:hover { background: var(--cyan-d); box-shadow: 0 14px 30px -12px rgba(37,168,203,.95); }
.tv-ink { background: var(--ink); color: #fff; }
.tv-ink:hover { background: #1B2530; }
.tv-line { border-color: var(--line-2); color: var(--ink); background: #fff; }
.tv-line:hover { border-color: var(--ink); }
.tv-sm { padding: 9px 18px; font-size: .9rem; }

/* ---- hero ------------------------------------------------------- */
.tv-hero { position: relative; padding: 68px 0 40px; overflow: hidden; }
/* Two soft cyan washes and a hairline grid. On white, a flat panel reads
   as an empty div; this reads as paper with light on it. */
.tv-hero::before {
  content: ''; position: absolute; inset: -20% -10% auto -10%; height: 620px; z-index: 0;
  background:
    radial-gradient(46% 60% at 78% 18%, rgba(37,168,203,.18) 0%, rgba(37,168,203,0) 70%),
    radial-gradient(40% 52% at 12% 4%,  rgba(37,168,203,.10) 0%, rgba(37,168,203,0) 72%);
}
.tv-grid-bg {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: linear-gradient(var(--line) 1px, transparent 1px),
                    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 62px 62px;
  mask-image: radial-gradient(70% 60% at 50% 20%, #000 0%, transparent 78%);
  opacity: .5;
}
.tv-hero-grid {
  position: relative; z-index: 2; display: grid; gap: 54px;
  grid-template-columns: 1.05fr .95fr; align-items: start;
}
/* The front door's hero: one centred column. It was the left half of the grid
   above, with the sign-in card on the right; sign-in lives at /login now, and a
   two-column hero with one column empty reads as a layout with a hole in it. */
.tv-hero-solo {
  position: relative; z-index: 2; max-width: 880px; text-align: center;
  padding: 16px 0 22px;
}
.tv-hero-solo .tv-lede { margin-inline: auto; max-width: 58ch; }
.tv-hero-solo .tv-cta { justify-content: center; }
.tv-hero-solo .tv-trust { justify-content: center; gap: 20px 44px; }
.tv-pill {
  display: inline-flex; align-items: center; gap: 9px; background: var(--cyan-w);
  color: var(--cyan-d); border: 1px solid rgba(37,168,203,.24);
  border-radius: 999px; padding: 7px 15px 7px 8px; font-size: .82rem; font-weight: 600;
}
.tv-pill b {
  background: var(--cyan); color: #fff; border-radius: 999px;
  padding: 3px 10px; font-size: .72rem; letter-spacing: .04em; text-transform: uppercase;
}
.tv-h1 {
  margin: 24px 0 0; font-size: clamp(2.6rem, 5.6vw, 4.35rem); line-height: 1.02;
  letter-spacing: -.035em; font-weight: 600;
}
.tv-h1 em { font-family: 'Instrument Serif', Georgia, serif; font-style: italic; font-weight: 400; color: var(--cyan); letter-spacing: -.01em; }
.tv-lede { color: var(--ink-2); font-size: 1.09rem; line-height: 1.68; margin: 22px 0 0; max-width: 48ch; font-weight: 300; }
.tv-lede b { color: var(--ink); font-weight: 600; }
.tv-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }
.tv-trust { display: flex; flex-wrap: wrap; gap: 26px; margin-top: 34px; padding-top: 26px; border-top: 1px solid var(--line); }
.tv-trust div b { display: block; font-size: 1.42rem; font-weight: 700; letter-spacing: -.02em; }
.tv-trust div span { color: var(--ink-3); font-size: .84rem; }

/* ---- the auth card ---------------------------------------------- */
.tv-card {
  background: #fff; border: 1px solid var(--line); border-radius: 22px;
  padding: 26px 26px 28px; box-shadow: 0 28px 60px -34px rgba(11,16,21,.3);
}
.tv-card-hd h2 { margin: 0 0 5px; font-size: 1.3rem; letter-spacing: -.02em; }
.tv-card-hd p  { margin: 0 0 18px; color: var(--ink-3); font-size: .92rem; }
.tv .tabs { display: flex; gap: 6px; background: var(--paper-2); padding: 4px; border-radius: 12px; margin-bottom: 18px; }
.tv .tabs button {
  flex: 1; border: 0; background: transparent; font: inherit; font-size: .92rem; font-weight: 600;
  color: var(--ink-3); padding: 9px; border-radius: 9px; cursor: pointer; transition: .18s;
}
.tv .tabs button.active { background: #fff; color: var(--ink); box-shadow: 0 1px 3px rgba(11,16,21,.12); }
/* Direct child only. `.field span` also matched the nested required marker, so
   the asterisk became its own block and pushed the input down a line. */
.tv .field > span { display: block; font-size: .82rem; font-weight: 600; color: var(--ink-2); margin-bottom: 6px; }
.tv .field .req { display: inline; color: var(--cyan); margin: 0 0 0 2px; }
.tv .field > span .muted { font-weight: 400; }
.tv .field input {
  width: 100%; border: 1.5px solid var(--line); border-radius: 11px; padding: 11px 13px;
  font: inherit; font-size: .95rem; background: #fff; color: var(--ink); transition: border-color .16s, box-shadow .16s;
}
.tv .field input:focus { outline: 0; border-color: var(--cyan); box-shadow: 0 0 0 3px rgba(37,168,203,.16); }
.tv .stack { display: grid; gap: 13px; }
.tv .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }
.tv .btn.block { width: 100%; }
.tv .btn.lg { padding: 13px 20px; font-size: .98rem; }
.tv .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--cyan); color: #fff; border: 1.5px solid var(--cyan); border-radius: 11px;
  font: inherit; font-weight: 600; padding: 11px 18px; cursor: pointer; transition: .18s;
}
.tv .btn:hover { background: var(--cyan-d); border-color: var(--cyan-d); }
.tv .btn.ghost { background: #fff; color: var(--ink); border-color: var(--line-2); }
.tv .btn.ghost:hover { background: var(--paper-2); border-color: var(--ink-3); }
.tv .btn-link { background: none; border: 0; color: var(--cyan-d); font: inherit; font-size: .9rem; cursor: pointer; }
.tv .btn-link.block { width: 100%; }
.tv .small { font-size: .84rem; }
.tv .muted { color: var(--ink-3); }
.tv .center { text-align: center; }

/* auth.js toggles the login / register / OTP forms by adding and removing this
   class. It lives in style.css, which the APP loads — the public pages load only
   this sheet, so without a copy here every form on /login showed at once. The
   !important matches style.css so the two behave identically. */
.hidden { display: none !important; }

/* ---- section furniture ------------------------------------------ */
.tv-sec { padding: 92px 0; }
.tv-sec.alt { background: var(--paper-2); border-block: 1px solid var(--line); }
.tv-kicker {
  display: inline-flex; align-items: center; gap: 9px; color: var(--cyan-d);
  font-size: .76rem; font-weight: 700; letter-spacing: .17em; text-transform: uppercase;
}
.tv-kicker::before { content: ''; width: 26px; height: 1.5px; background: var(--cyan); }
.tv-h2 { font-size: clamp(1.9rem, 3.6vw, 2.9rem); line-height: 1.1; letter-spacing: -.032em; margin: 16px 0 0; font-weight: 600; }
.tv-h2 em { font-family: 'Instrument Serif', Georgia, serif; font-style: italic; font-weight: 400; color: var(--cyan); }
.tv-sub { color: var(--ink-2); font-size: 1.03rem; line-height: 1.66; margin: 16px 0 0; max-width: 60ch; font-weight: 300; }

/* ---- what we do (bento) ----------------------------------------- */
.tv-bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: 16px; margin-top: 44px; }
.tv-tile {
  background: #fff; border: 1px solid var(--line); border-radius: 18px; padding: 26px;
  grid-column: span 2; transition: border-color .2s, transform .2s, box-shadow .2s;
}
.tv-tile:hover { border-color: var(--line-2); transform: translateY(-3px); box-shadow: 0 18px 40px -28px rgba(11,16,21,.4); }
.tv-tile.wide { grid-column: span 3; }
.tv-tile.full { grid-column: span 6; background: var(--ink); color: #fff; border-color: var(--ink); }
.tv-tile.full .tv-tile-b { color: rgba(255,255,255,.68); }
.tv-ico {
  width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  background: var(--cyan-w); color: var(--cyan-d); font-size: 1.05rem; margin-bottom: 16px;
}
.tv-tile.full .tv-ico { background: rgba(255,255,255,.12); color: #7FD4EA; }
.tv-tile h3 { margin: 0 0 8px; font-size: 1.08rem; letter-spacing: -.015em; }
.tv-tile-b { color: var(--ink-2); font-size: .94rem; line-height: 1.6; margin: 0; font-weight: 300; }

/* ---- steps ------------------------------------------------------- */
.tv-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; margin-top: 48px; }
.tv-step { padding: 26px 22px 0; border-top: 2px solid var(--line); position: relative; }
.tv-step::before {
  content: ''; position: absolute; top: -2px; left: 0; width: 0; height: 2px;
  background: var(--cyan); transition: width .5s ease;
}
.tv-step.lit::before { width: 100%; }
.tv-step b { display: block; font-size: .78rem; color: var(--cyan-d); letter-spacing: .12em; margin-bottom: 10px; }
.tv-step h3 { margin: 0 0 8px; font-size: 1.06rem; letter-spacing: -.015em; }
.tv-step p { margin: 0; color: var(--ink-2); font-size: .92rem; line-height: 1.6; font-weight: 300; }

/* ---- regions ----------------------------------------------------- */
.tv-regions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 44px; }
.tv-region {
  border: 1px solid var(--line); border-radius: 18px; padding: 24px; background: #fff;
  position: relative; overflow: hidden;
  transition: border-color .25s, transform .25s, box-shadow .25s;
}
.tv-region:hover { border-color: var(--line-2); transform: translateY(-3px); box-shadow: 0 18px 40px -30px rgba(11,16,21,.45); }
.tv-region::after {
  content: ''; position: absolute; right: -28px; bottom: -28px; width: 110px; height: 110px;
  border-radius: 50%; background: var(--cyan-w);
}
.tv-region > * { position: relative; z-index: 1; }
/* An icon in a disc, not a flag emoji: the emoji renders as a different size,
   weight and even a different picture on every platform, and on Windows it is
   two letters in a box. Font Awesome is the same everywhere. */
.tv-flag {
  width: 46px; height: 46px; border-radius: 14px; display: grid; place-items: center;
  background: var(--cyan-w); color: var(--cyan-d); font-size: 1.12rem;
  transition: transform .25s cubic-bezier(.2,.9,.25,1), background .25s, color .25s;
}
.tv-region:hover .tv-flag { transform: rotate(-6deg) scale(1.06); background: var(--cyan); color: #fff; }
.tv-code {
  font-size: .72rem; font-weight: 700; letter-spacing: .14em; color: var(--ink-3);
  border: 1px solid var(--line-2); border-radius: 5px; padding: 2px 6px; vertical-align: middle;
  margin-left: 6px;
}
.tv-region h3 { margin: 12px 0 6px; font-size: 1.1rem; letter-spacing: -.015em; }
.tv-region p { margin: 0; color: var(--ink-2); font-size: .9rem; line-height: 1.55; font-weight: 300; }

/* ---- pricing ----------------------------------------------------- */
.tv-plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 18px; margin-top: 44px; }
.tv-plan { background: #fff; border: 1px solid var(--line); border-radius: 20px; padding: 28px; display: flex; flex-direction: column; }
.tv-plan.hot { border-color: var(--cyan); box-shadow: 0 0 0 3px rgba(37,168,203,.14); }
.tv-plan .tag {
  /* align-self, not display:inline-block: the card is a flex column, so a block
     child stretches to the full width and the pill becomes a banner. */
  align-self: flex-start;
  background: var(--cyan); color: #fff; border-radius: 999px;
  padding: 4px 12px; font-size: .69rem; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; margin-bottom: 12px;
}
.tv-plan h3 { margin: 0 0 6px; font-size: 1.16rem; letter-spacing: -.015em; }
.tv-plan .price { font-size: 2.15rem; font-weight: 700; letter-spacing: -.035em; margin: 10px 0 2px; }
.tv-plan .price small { font-size: .88rem; font-weight: 400; color: var(--ink-3); letter-spacing: 0; }
.tv-plan .blurb { color: var(--ink-2); font-size: .92rem; line-height: 1.55; margin: 0 0 18px; font-weight: 300; }
.tv-plan ul { list-style: none; margin: 0 0 24px; padding: 0; display: grid; gap: 10px; }
.tv-plan li { display: flex; gap: 10px; align-items: flex-start; font-size: .93rem; color: var(--ink-2); }
.tv-plan li i { color: var(--cyan); font-size: .78rem; margin-top: .35em; }
.tv-plan .tv-btn { margin-top: auto; justify-content: center; }

/* ---- closer + footer --------------------------------------------- */
.tv-end {
  background: var(--ink); color: #fff; border-radius: 26px; padding: 64px 40px; text-align: center;
  margin: 92px auto; position: relative; overflow: hidden;
}
.tv-end::before {
  content: ''; position: absolute; inset: auto -10% -60% -10%; height: 340px;
  background: radial-gradient(50% 100% at 50% 100%, rgba(37,168,203,.55) 0%, rgba(37,168,203,0) 72%);
}
.tv-end > * { position: relative; z-index: 1; }
.tv-end h2 { font-size: clamp(1.9rem, 3.8vw, 2.9rem); line-height: 1.1; letter-spacing: -.032em; margin: 0; font-weight: 600; }
.tv-end h2 em { font-family: 'Instrument Serif', Georgia, serif; font-style: italic; font-weight: 400; color: #7FD4EA; }
.tv-end p { color: rgba(255,255,255,.66); margin: 18px auto 30px; max-width: 52ch; font-weight: 300; }

.tv-foot { border-top: 1px solid var(--line); padding: 34px 0 46px; background: var(--paper); }
.tv-foot .tv-wrap { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; }
.tv-foot nav { margin-left: auto; display: flex; flex-wrap: wrap; gap: 4px 24px; }
/* Padding, not just line-height: these were 22px tall, well under a thumb. */
.tv-foot nav a { color: var(--ink-3); text-decoration: none; font-size: .9rem;
  display: inline-flex; align-items: center; min-height: 34px; }
.tv-foot nav a:hover { color: var(--cyan-d); }

/* ---- reveal on scroll -------------------------------------------- */
.js .tv-up { opacity: 0; transform: translateY(20px); transition: opacity .6s ease, transform .6s cubic-bezier(.2,.8,.2,1); }
.js .tv-up.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .js .tv-up { opacity: 1; transform: none } }

/* ---- responsive --------------------------------------------------- */
@media (max-width: 980px) {
  .tv-hero-grid { grid-template-columns: 1fr; gap: 40px; }
  .tv-steps, .tv-regions { grid-template-columns: repeat(2, 1fr); }
  .tv-tile, .tv-tile.wide { grid-column: span 3; }
}
@media (max-width: 640px) {
  .tv-sec { padding: 64px 0 }
  .tv-steps, .tv-regions { grid-template-columns: 1fr; }
  .tv-tile, .tv-tile.wide, .tv-tile.full { grid-column: span 6; }
  .tv-end { padding: 46px 22px; border-radius: 20px; }
  .tv .grid-2 { grid-template-columns: 1fr; }
}


/* =====================================================================
   Shared page furniture — pricing, privacy, terms.
   The landing sections above are one-offs; these are what any additional
   page is built from, so a fourth page is markup rather than more CSS.
   ===================================================================== */

/* ---- page head (a shorter hero for an inside page) ------------------ */
.tv-head { position: relative; padding: 62px 0 52px; overflow: hidden; border-bottom: 1px solid var(--line); }
.tv-head::before {
  content: ''; position: absolute; inset: -60% -10% auto -10%; height: 460px; z-index: 0;
  background: radial-gradient(44% 62% at 72% 60%, rgba(37,168,203,.16) 0%, rgba(37,168,203,0) 70%);
}
.tv-head .tv-wrap { position: relative; z-index: 1; }
.tv-head h1 {
  font-size: clamp(2.1rem, 4.4vw, 3.4rem); line-height: 1.06; letter-spacing: -.038em;
  margin: 16px 0 0; font-weight: 600; max-width: 20ch;
}
.tv-head h1 em { font-family: 'Instrument Serif', Georgia, serif; font-style: italic; font-weight: 400; color: var(--cyan); }
.tv-head p { color: var(--ink-2); font-size: 1.04rem; line-height: 1.68; margin: 16px 0 0; max-width: 58ch; font-weight: 300; }

/* ---- crumbs --------------------------------------------------------- */
.tv-crumb { display: flex; align-items: center; gap: 9px; font-size: .84rem; color: var(--ink-3); }
.tv-crumb a { color: var(--ink-3); text-decoration: none; }
.tv-crumb a:hover { color: var(--cyan-d); }
.tv-crumb i { font-size: .6rem; }

/* ---- long-form prose ------------------------------------------------ */
.tv-prose { max-width: 74ch; }
.tv-prose h2 {
  font-size: 1.42rem; letter-spacing: -.024em; margin: 44px 0 12px; font-weight: 600;
  scroll-margin-top: 96px;
}
.tv-prose h2:first-child { margin-top: 0; }
.tv-prose h3 { font-size: 1.05rem; letter-spacing: -.015em; margin: 26px 0 8px; font-weight: 600; }
.tv-prose p, .tv-prose li { color: var(--ink-2); font-size: 1rem; line-height: 1.78; font-weight: 300; }
.tv-prose p { margin: 0 0 14px; }
.tv-prose ul, .tv-prose ol { margin: 0 0 18px; padding-left: 22px; }
.tv-prose li { margin-bottom: 8px; }
.tv-prose b, .tv-prose strong { color: var(--ink); font-weight: 600; }
.tv-prose a { color: var(--cyan-d); }
.tv-prose hr { border: 0; border-top: 1px solid var(--line); margin: 40px 0; }
.tv-note {
  background: var(--cyan-w); border: 1px solid rgba(37,168,203,.22); border-radius: 14px;
  padding: 18px 20px; margin: 0 0 26px;
}
.tv-note p { margin: 0; color: var(--ink-2); }
.tv-note b { color: var(--ink); }

/* ---- a sticky contents rail beside the prose ------------------------ */
.tv-doc { display: grid; grid-template-columns: 220px 1fr; gap: 54px; align-items: start; }
.tv-toc { position: sticky; top: 96px; }
.tv-toc span {
  display: block; font-size: .72rem; font-weight: 700; letter-spacing: .17em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 12px;
}
.tv-toc a {
  display: block; padding: 7px 0 7px 14px; border-left: 2px solid var(--line);
  color: var(--ink-2); text-decoration: none; font-size: .9rem; transition: .16s;
}
.tv-toc a:hover { border-left-color: var(--cyan); color: var(--ink); }

/* ---- comparison table ----------------------------------------------- */
.tv-table-wrap { overflow-x: auto; margin-top: 40px; border: 1px solid var(--line); border-radius: 16px; background: #fff; }
.tv-table { width: 100%; border-collapse: collapse; min-width: 640px; }
.tv-table th, .tv-table td { padding: 15px 18px; text-align: left; border-bottom: 1px solid var(--line); font-size: .94rem; }
.tv-table thead th { font-size: .78rem; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); font-weight: 700; background: var(--paper-2); }
.tv-table tbody tr:last-child td { border-bottom: 0; }
.tv-table td.c, .tv-table th.c { text-align: center; }
.tv-table .yes { color: var(--cyan); }
.tv-table .no  { color: var(--line-2); }
.tv-table tbody tr { transition: background .16s; }
.tv-table tbody tr:hover { background: var(--paper-2); }

/* ---- FAQ (native details, so it works with no JavaScript) ----------- */
.tv-faq { margin-top: 40px; border-top: 1px solid var(--line); }
.tv-faq details { border-bottom: 1px solid var(--line); }
.tv-faq summary {
  list-style: none; cursor: pointer; padding: 20px 40px 20px 0; position: relative;
  font-size: 1.04rem; font-weight: 600; letter-spacing: -.015em;
}
.tv-faq summary::-webkit-details-marker { display: none; }
.tv-faq summary::after {
  content: '\f067'; font-family: 'Font Awesome 6 Free'; font-weight: 900; font-size: .8rem;
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%); color: var(--cyan);
  transition: transform .25s;
}
.tv-faq details[open] summary::after { content: '\f068'; }
.tv-faq .a { padding: 0 0 22px; color: var(--ink-2); line-height: 1.75; font-weight: 300; max-width: 74ch; }
.tv-faq .a p { margin: 0 0 12px; }
.tv-faq .a p:last-child { margin: 0; }

/* ---- a small CTA band ------------------------------------------------ */
.tv-band {
  display: flex; flex-wrap: wrap; align-items: center; gap: 20px;
  border: 1px solid var(--line); border-radius: 20px; padding: 28px 30px;
  background: var(--paper-2); margin-top: 56px;
}
.tv-band h3 { margin: 0 0 4px; font-size: 1.16rem; letter-spacing: -.02em; }
.tv-band p { margin: 0; color: var(--ink-2); font-size: .95rem; font-weight: 300; }
.tv-band .tv-btn { margin-left: auto; }

@media (max-width: 900px) {
  .tv-doc { grid-template-columns: 1fr; gap: 30px; }
  .tv-toc { position: static; display: none; }
  .tv-band .tv-btn { margin-left: 0; }
}


/* =====================================================================
   Entrances.
   Two mechanisms, deliberately: .tv-rise fires on load with a stagger (the
   hero, which is on screen before anyone scrolls), .tv-up fires on scroll
   (everything below it). Both are keyed off .js and both stand down under
   prefers-reduced-motion — an entrance that hides content from someone who
   asked for less motion is not an entrance, it is a bug.
   ===================================================================== */
.js .tv-rise {
  opacity: 0; transform: translateY(18px);
  animation: tv-rise .78s cubic-bezier(.2,.8,.2,1) forwards;
  animation-delay: var(--d, 0s);
}
@keyframes tv-rise { to { opacity: 1; transform: none } }
@media (prefers-reduced-motion: reduce) {
  .js .tv-rise { opacity: 1; transform: none; animation: none }
}

/* The hero wash drifts, very slowly. Static, it reads as a flat panel; at this
   speed it reads as light moving across paper and nobody consciously sees it. */
@media (prefers-reduced-motion: no-preference) {
  .tv-hero::before { animation: tv-drift 22s ease-in-out infinite alternate; }
}
@keyframes tv-drift {
  from { transform: translate3d(0, 0, 0) scale(1) }
  to   { transform: translate3d(-2.5%, 1.5%, 0) scale(1.06) }
}

/* Counters land on their real number; the element carries the final text as
   its content so a page without JavaScript still reads correctly. */
.tv-trust div b { font-variant-numeric: tabular-nums; }

/* Buttons get a sweep on hover rather than only a colour change — it is the
   difference between "this is clickable" and "this responded to me". */
.tv-btn { position: relative; overflow: hidden; }
.tv-btn > * { position: relative; z-index: 1; }
.tv-btn::after {
  content: ''; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(255,255,255,.28) 50%, transparent 80%);
  transform: translateX(-120%);
}
.tv-btn:hover::after { transform: translateX(120%); transition: transform .7s cubic-bezier(.3,.7,.3,1); }
/* …and a lift. The sweep alone is easy to miss on the outline buttons. */
.tv-btn:hover { transform: translateY(-1.5px); }
.tv-btn:active { transform: translateY(1px); }
@media (prefers-reduced-motion: reduce) {
  .tv-btn::after { display: none }
  .tv-btn:hover { transform: none }
}

/* Nav condenses once the page has moved, so the content gets the height back. */
.tv-nav .tv-wrap { transition: height .25s cubic-bezier(.2,.8,.2,1); }
.tv-nav.stuck .tv-wrap { height: 60px; }

/* The masthead mark nudges on hover — a two-pixel tell that it is a link home. */
.tv-mark img { transition: transform .3s cubic-bezier(.2,.9,.25,1); }
.tv-mark:hover img { transform: translateY(-2px) rotate(-8deg); }

/* Bento icons lift with their tile. */
.tv-ico { transition: transform .25s cubic-bezier(.2,.9,.25,1); }
.tv-tile:hover .tv-ico { transform: translateY(-3px) scale(1.06); }

/* Focus ring, once, for everything that takes focus. Keyboard users get a
   visible target without the mouse ever seeing a ring. */
.tv a:focus-visible, .tv button:focus-visible, .tv summary:focus-visible, .tv input:focus-visible {
  outline: 2px solid var(--cyan); outline-offset: 3px; border-radius: 6px;
}


/* =====================================================================
   Mobile pass.
   The breakpoints above reflow the grids; these tune the things that only
   look wrong once a grid is one column — type that is too large for the
   measure, section padding sized for a desktop, and touch targets.
   ===================================================================== */
@media (max-width: 640px) {
  .tv-h1  { font-size: clamp(2.15rem, 9.4vw, 2.9rem); letter-spacing: -.03em; }
  .tv-h2  { font-size: clamp(1.68rem, 7.4vw, 2.2rem); }
  .tv-lede { font-size: 1rem; }
  .tv-hero { padding: 40px 0 24px; }
  .tv-hero-grid { gap: 34px; }

  /* Full-width buttons on a phone: two 48%-wide buttons side by side is two
     targets that are both slightly too small. */
  .tv-cta { flex-direction: column; align-items: stretch; }
  .tv-cta .tv-btn { justify-content: center; width: 100%; padding: 14px 22px; }

  .tv-trust { gap: 18px 26px; }
  .tv-trust div { min-width: 44%; }

  .tv-card { padding: 22px 18px 24px; border-radius: 18px; }
  .tv-tile { padding: 22px 20px; }
  .tv-region { padding: 20px; }
  .tv-plan  { padding: 24px 22px; }
  .tv-step  { padding: 22px 0 0; }

  .tv-head { padding: 40px 0 36px; }
  .tv-prose h2 { font-size: 1.24rem; margin-top: 34px; }
  .tv-prose p, .tv-prose li { font-size: .97rem; line-height: 1.72; }

  .tv-end { padding: 40px 20px; margin: 60px auto; border-radius: 18px; }
  .tv-end .tv-btn { width: 100%; justify-content: center; }
  .tv-band { padding: 22px; border-radius: 16px; }
  .tv-band .tv-btn { width: 100%; justify-content: center; }

  .tv-foot { padding: 26px 0 36px; }
  .tv-foot .tv-wrap { flex-direction: column; align-items: flex-start; gap: 16px; }
  .tv-foot nav { margin-left: 0; gap: 14px 20px; }

  .tv-faq summary { font-size: .98rem; padding: 17px 34px 17px 0; }
}

/* Never let a long word or a wide table push the page sideways. */
.tv { overflow-x: hidden; }
.tv-h1, .tv-h2, .tv-prose h2, .tv-head h1 { overflow-wrap: break-word; }

/* ---- footer columns ------------------------------------------------- */
.tv-foot-cols {
  display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 34px;
  padding-bottom: 30px;
}
.tv-foot-brand p { color: var(--ink-3); font-size: .92rem; line-height: 1.6; margin: 14px 0 0; max-width: 34ch; font-weight: 300; }
.tv-foot nav { display: flex; flex-direction: column; gap: 10px; margin-left: 0; }
.tv-foot nav span {
  font-size: .72rem; font-weight: 700; letter-spacing: .15em; text-transform: uppercase;
  color: var(--ink); margin-bottom: 2px;
}
.tv-foot-base {
  display: flex; flex-wrap: wrap; gap: 14px; justify-content: space-between;
  border-top: 1px solid var(--line); padding-top: 20px;
  color: var(--ink-3); font-size: .86rem;
}
@media (max-width: 780px) {
  .tv-foot-cols { grid-template-columns: 1fr 1fr; gap: 26px; }
  .tv-foot-brand { grid-column: 1 / -1; }
}
@media (max-width: 460px) { .tv-foot-cols { grid-template-columns: 1fr; } }

/* ---- centred single-column page (login) ----------------------------- */
.tv-auth-wrap {
  display: grid; place-items: center; padding: 54px 0 84px; min-height: 62vh;
}
.tv-auth { width: min(440px, 100%); }
.tv-auth .tv-card { padding: 30px 28px 32px; }
.tv-auth-foot { text-align: center; margin-top: 18px; color: var(--ink-3); font-size: .9rem; }
.tv-auth-foot a { color: var(--cyan-d); }

/* ---- about: values / desks ------------------------------------------ */
.tv-two { display: grid; grid-template-columns: 1.1fr .9fr; gap: 54px; align-items: start; }
@media (max-width: 900px) { .tv-two { grid-template-columns: 1fr; gap: 32px; } }

.tv-stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-top: 40px; }
.tv-stat-row div { border-left: 2px solid var(--cyan); padding-left: 16px; }
.tv-stat-row b { display: block; font-size: 1.7rem; font-weight: 700; letter-spacing: -.03em; }
.tv-stat-row span { color: var(--ink-3); font-size: .86rem; }
@media (max-width: 700px) { .tv-stat-row { grid-template-columns: 1fr 1fr; gap: 22px; } }

/* ---- contact channels ------------------------------------------------ */
.tv-channels { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; margin-top: 40px; }
.tv-channel {
  border: 1px solid var(--line); border-radius: 18px; padding: 26px; background: #fff;
  transition: border-color .2s, transform .2s;
}
.tv-channel:hover { border-color: var(--line-2); transform: translateY(-2px); }
.tv-channel h3 { margin: 14px 0 6px; font-size: 1.05rem; letter-spacing: -.015em; }
.tv-channel p { margin: 0 0 14px; color: var(--ink-2); font-size: .93rem; line-height: 1.6; font-weight: 300; }
.tv-channel .tv-btn { width: 100%; justify-content: center; }

/* Honeypot. Positioned off-screen rather than display:none — some bots skip
   inputs that are display:none, which is exactly the ones we want them to fill.
   aria-hidden and tabindex="-1" on the field keep it away from real people. */
.tv-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Selects match the text inputs — a form where one control is styled and the
   next is the browser default reads as unfinished. */
.tv .field select {
  width: 100%; border: 1.5px solid var(--line); border-radius: 11px; padding: 11px 13px;
  font: inherit; font-size: .95rem; background: #fff; color: var(--ink);
  transition: border-color .16s, box-shadow .16s;
}
.tv .field select:focus { outline: 0; border-color: var(--cyan); box-shadow: 0 0 0 3px rgba(37,168,203,.16); }
.tv .field textarea {
  width: 100%; border: 1.5px solid var(--line); border-radius: 11px; padding: 11px 13px;
  font: inherit; font-size: .95rem; background: #fff; color: var(--ink); resize: vertical;
  transition: border-color .16s, box-shadow .16s;
}
.tv .field textarea:focus { outline: 0; border-color: var(--cyan); box-shadow: 0 0 0 3px rgba(37,168,203,.16); }

/* ---- grouped nav dropdowns ------------------------------------------------
   No JavaScript: hover opens it for a mouse, :focus-within opens it for a
   keyboard. The button takes focus first, which satisfies :focus-within and
   reveals the links, so they become tabbable in the same motion. */
.tv-drop { position: relative; }
.tv-drop-t {
  display: inline-flex; align-items: center; gap: 7px; background: none; border: 0;
  font: inherit; font-size: .93rem; font-weight: 500; color: var(--ink-2);
  cursor: pointer; padding: 0; transition: color .15s ease;
}
.tv-drop-t i { font-size: .62rem; transition: transform .18s ease; }
.tv-drop:hover .tv-drop-t, .tv-drop:focus-within .tv-drop-t, .tv-drop.on .tv-drop-t { color: var(--ink); }
.tv-drop:hover .tv-drop-t i, .tv-drop:focus-within .tv-drop-t i { transform: rotate(180deg); }
.tv-drop.on .tv-drop-t { color: var(--cyan-d); }

.tv-drop-m {
  position: absolute; top: calc(100% + 12px); left: 50%; translate: -50% 0;
  min-width: 230px; display: flex; flex-direction: column; gap: 2px;
  background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 8px;
  box-shadow: 0 18px 44px -18px rgba(11,16,21,.28);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
/* A gap between the button and the panel would close the menu as the pointer
   crossed it. This bridges it without moving the panel. */
.tv-drop::after { content: ''; position: absolute; top: 100%; left: 0; right: 0; height: 14px; }
.tv-drop:hover .tv-drop-m, .tv-drop:focus-within .tv-drop-m {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.tv-nav nav .tv-drop-m a {
  padding: 9px 12px; border-radius: 9px; font-size: .91rem; white-space: nowrap;
  transition: background .14s ease, color .14s ease;
}
.tv-nav nav .tv-drop-m a::after { display: none; }
.tv-nav nav .tv-drop-m a:hover { background: var(--paper-2); color: var(--ink); }
.tv-nav nav .tv-drop-m a[aria-current=page] { color: var(--cyan-d); background: var(--cyan-w); }

@media (max-width: 860px) {
  /* In the burger menu there is nothing to drop down into — the group becomes
     a heading with its links indented under it, always visible. */
  .tv-drop { position: static; border-bottom: 1px solid var(--line); }
  .tv-drop::after { display: none; }
  .tv-drop-t {
    width: 100%; justify-content: space-between; padding: 14px 4px;
    font-size: .76rem; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
    color: var(--ink-3); cursor: default; pointer-events: none;
  }
  .tv-drop-t i { display: none; }
  .tv-drop-m {
    position: static; translate: none; transform: none; opacity: 1; visibility: visible;
    min-width: 0; border: 0; box-shadow: none; padding: 0 0 10px; background: none; gap: 0;
  }
  .tv-nav nav .tv-drop-m a { padding: 11px 4px 11px 14px; border-bottom: 0; font-size: .97rem; }
}

/* ---- masthead account menu, when somebody is signed in ---------------------
   Same <details> trick as the app's top bar, and deliberately the same
   `usermenu` class: ui.js already closes an open one on an outside click or on
   Escape, so this needs no JavaScript of its own. The rules are scoped under
   .tv-nav because a catalogue page loads style.css too, whose .usermenu block
   is written in the app's tokens. */
.tv-user { position: relative; }
.tv-user > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 11px 3px 3px; background: #fff;
  border: 1.5px solid var(--line-2); border-radius: 999px; transition: border-color .18s;
}
.tv-user > summary::-webkit-details-marker { display: none; }
.tv-user > summary:hover { border-color: var(--ink); }
.tv-user > summary i { font-size: .62rem; color: var(--ink-3); transition: transform .18s ease; }
.tv-user[open] > summary i { transform: rotate(180deg); }
.tv-ava {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--cyan); color: #fff; font-weight: 700; font-size: .9rem; line-height: 1;
}
.tv-nav .tv-user .menu {
  position: absolute; right: 0; top: calc(100% + 12px); z-index: 70; width: 252px;
  display: grid; gap: 2px; padding: 8px;
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 18px 44px -18px rgba(11,16,21,.28);
}
.tv-nav .tv-user .menu-head {
  display: grid; gap: 3px; padding: 10px 10px 12px; margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.tv-nav .tv-user .menu-head b { font-size: .92rem; color: var(--ink); }
/* An address longer than the panel must wrap rather than widen it. */
.tv-nav .tv-user .menu-head span { font-size: .79rem; color: var(--ink-3); overflow-wrap: anywhere; }
.tv-nav .tv-user .tv-chip {
  justify-self: start; margin-top: 5px; padding: 3px 9px; border-radius: 999px;
  background: var(--cyan-w); color: var(--cyan-d); font-size: .72rem; font-weight: 700;
}
.tv-nav .tv-user .menu a, .tv-nav .tv-user .menu button {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px;
  border: 0; border-radius: 9px; background: none; text-align: left; text-decoration: none;
  font: inherit; font-size: .88rem; font-weight: 500; color: var(--ink); cursor: pointer;
}
.tv-nav .tv-user .menu i { width: 16px; color: var(--ink-3); }
.tv-nav .tv-user .menu a:hover, .tv-nav .tv-user .menu button:hover { background: var(--cyan-w); color: var(--cyan-d); }
.tv-nav .tv-user .menu a:hover i, .tv-nav .tv-user .menu button:hover i { color: var(--cyan-d); }
.tv-nav .tv-dash i { font-size: .82rem; }

/* 940px is where the full menu, the pill and the avatar stop fitting on one
   line — below it the links start colliding with the actions. The avatar stays,
   because it is the only way to sign out, and Dashboard is the first item inside
   it, so nothing becomes unreachable. */
@media (max-width: 940px) { .tv-dash { display: none; } }

/* The contextual strip under the masthead on catalogue pages — "← All packages"
   and the like. The masthead is the site's; this row is the page's. */
.pub-subnav { border-bottom: 1px solid var(--line, #E3EAEE); background: #fff; }
.pub-subnav .tv-wrap { display: flex; align-items: center; gap: 18px; min-height: 48px; flex-wrap: wrap; }
.pub-subnav a { font-size: .9rem; color: #4C5860; text-decoration: none; display: inline-flex;
                align-items: center; gap: 7px; }
.pub-subnav a:hover { color: #0B1015; }
.pub-subnav a.active { color: #17819F; font-weight: 600; }

/* ---- the auth card, on /login and on the home page -------------------------
   One block for both: it is literally the same markup in two places, and the
   two had drifted into different spacing. Scoped to #authCard so it follows the
   card wherever it is rendered rather than to the page around it. */
#authCard { padding: clamp(26px, 4vw, 34px) clamp(22px, 3.4vw, 32px) clamp(26px, 3.4vw, 32px); }
#authCard .tv-card-hd { margin-bottom: 22px; }
#authCard .tv-card-hd h2 { margin: 0 0 6px; letter-spacing: -.02em; }
#authCard .tv-card-hd p  { margin: 0; color: var(--ink-3); font-size: .92rem; line-height: 1.5; }

/* A 40px row is a real tap target; the old one was whatever the text needed. */
#authCard .tabs { margin-bottom: 22px; }
#authCard .tabs button { min-height: 38px; }

/* Fields breathe. 14px between a message-bearing field and the next label was
   tight enough that a red line looked like it belonged to the wrong input. */
#authCard .stack { gap: 17px; }
#authCard .field > span { font-size: .84rem; margin-bottom: 7px; }
/* No `#authCard input { padding }` here. An ID selector out-ranks every
   class-based rule, so it beat the padding-right that keeps a long password
   clear of the show/hide button in formcheck.css — the text ran underneath the
   eye. `.tv .field input` already sets the padding these inputs need. */

/* The primary action separated from the fields, and the alternative separated
   from the primary — three things in a row all 100% wide read as one block. */
#authCard .stack > .btn.block.lg { margin-top: 4px; }
#authCard .stack > .btn.ghost.block {
  margin-top: 2px; position: relative; padding-top: 13px; padding-bottom: 13px;
}
#authCard .btn-link.block { width: 100%; margin-top: 2px; }

/* The register form's two-up row is 440px wide at most; below that it is two
   190px inputs, which is where "Full name" stops fitting its own placeholder. */
@media (max-width: 430px) { #authCard .grid-2 { grid-template-columns: 1fr; } }

#authCard .small.muted.center { margin: 14px 0 0; line-height: 1.5; }

/* The page around the card. */
.tv-auth-wrap { padding: clamp(38px, 6vw, 64px) 0 clamp(56px, 8vw, 88px); }
.tv-auth-foot { margin-top: 20px; line-height: 1.6; }

/* ---- the people behind the desks (about) ----------------------------------
   One card shape for the CEO and every desk owner. They were two layouts and
   drifted apart inside a day, so there is one now and the lead card is the same
   card at a wider span.

   Photos are uploaded by the platform owner in Admin -> Desk identity, at
   whatever size and shape their phone produced. Every dimension here is fixed
   and the image is cropped into it: one portrait shot in landscape must not be
   able to set the height of a row. */
.tv-desks {
  display: grid;
  /* Two across on a desktop, not four. At four the name wrapped onto two lines
     and the company onto three, which is a column of fragments rather than a
     card. */
  /* min(420px, 100%), not 420px: a bare minimum wider than the viewport makes
     the TRACK wider than the screen, and the whole page then scrolls sideways
     on a phone. */
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
  gap: 18px;
  margin-top: 44px;
  align-items: start;
}
.tv-deskcard {
  display: flex;
  gap: 18px;
  align-items: flex-start;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--paper, #fff);
  transition: border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
.tv-deskcard:hover {
  border-color: var(--line-2, #E1E4E9);
  transform: translateY(-2px);
  box-shadow: 0 18px 40px -30px rgba(11, 16, 21, .45);
}
.tv-deskcard-face {
  width: 84px; height: 84px; flex: 0 0 84px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center top;
  border: 3px solid var(--line-2, #E1E4E9);
  background: #EEF0F3;
}
.tv-deskcard-blank { display: grid; place-items: center; color: #9AA3AD; font-size: 1.6rem; }
.tv-deskcard-body { min-width: 0; }   /* so a long company name wraps instead of stretching the grid */
.tv-deskcard-kicker {
  display: block;
  font-size: .72rem; letter-spacing: .16em; text-transform: uppercase; font-weight: 700;
  color: var(--cyan, #25A8CB);
}
.tv-deskcard-name {
  margin: 6px 0 3px;
  font-size: 1.12rem; letter-spacing: -.015em; line-height: 1.25;
}
.tv-deskcard-role { font-size: .88rem; color: var(--ink-2); font-weight: 500; line-height: 1.45; }
.tv-deskcard-where {
  margin-top: 6px;
  font-size: .8rem; color: var(--ink-3); font-weight: 400;
}
.tv-deskcard-where i { font-size: .74em; opacity: .65; margin-right: 3px; }
.tv-deskcard-msg {
  margin: 12px 0 0;
  font-size: .9rem; line-height: 1.65; color: var(--ink-2); font-weight: 300;
  padding-left: 14px;
  border-left: 2px solid var(--line-2, #E1E4E9);
}
/* Staff on a desk, not the desk itself: the same card at a lighter weight. */
.tv-deskcard-staff { padding: 18px; gap: 14px; }
.tv-deskcard-staff .tv-deskcard-face { width: 58px; height: 58px; flex-basis: 58px; border-width: 2px; }
.tv-deskcard-staff .tv-deskcard-name { font-size: 1rem; margin-top: 5px; }
.tv-deskcard-staff .tv-deskcard-role { font-size: .82rem; }
.tv-deskcard-staff .tv-deskcard-msg  { font-size: .85rem; margin-top: 10px; }
/* Six columns above 900px so the three sizes of card divide the row evenly:
   a desk takes three, the CEO all six, a colleague two. The auto-fit track
   above still governs everything narrower, where each card is full width. */
@media (min-width: 900px) {
  .tv-desks { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  /* Every card two columns wide — three to a row, desks and colleagues alike.
     They flow one after another so a row is never left with a hole in it. */
  .tv-desks > .tv-deskcard { grid-column: span 2; align-self: stretch; }
}

/* Phones: the photo goes above the words rather than squeezing them into a
   column two words wide. */
@media (max-width: 560px) {
  .tv-desks { gap: 14px; }
  .tv-deskcard { flex-direction: column; gap: 14px; padding: 20px; }
}
