/* Springfield Sign payment — SSG "Neon Glow" language (Attaché + EPIClock).
   Full-viewport two-panel split. Real .ep/.badge pills, red neon glow in BOTH themes.
   The cross-origin light form is inverted to dark (tuned) in dark theme. CSP-safe:
   all styles here (no inline), same-origin assets only. */

* { box-sizing: border-box; }
html, body { height: 100%; }
body { margin: 0; background: var(--bg-page); color: var(--text-primary); font-family: var(--font-stack); -webkit-font-smoothing: antialiased; display: flex; flex-direction: column; min-height: 100vh; }
/* THE page glow. One soft red wash anchored at top-centre, fading down over the top third of the
   viewport, painted on <body> behind all content and pinned (background-attachment:fixed) so it
   does not scroll away. The transparent tab bar sits in this field, so the glow reads continuously
   from the very top down into the page instead of being a band stuck to the bar. Tuned brighter in
   dark, whisper-faint in light. */
/* LINEAR top-to-bottom, not a radial. A radial is centred, so it is dimmer on the sides — the card
   is on the RIGHT, so above it stayed dark however the radial was tuned (measured a near-black dip
   there). A linear top glow is UNIFORM across the full width: the rail and the card both sit under
   the same even red wash, so there is no dark patch above the embed at any width. It fades straight
   down. */
/* PLATEAU, not a spike: the glow holds near-full strength through the top ~16% (which covers the
   tab bar AND the top of the card, ~7% down) before fading. A glow that peaked only at y=0 dimmed
   right where the card's rounded corners are, so those corner notches showed the dim background as
   dark boxes against the white card. Held strong there, the corners sit in red, not dark. */
[data-theme="dark"] body {
  background:
    linear-gradient(to bottom, rgba(255,0,8,.16) 0%, rgba(255,0,8,.15) 15%, rgba(255,0,8,.07) 38%, rgba(255,0,8,0) 66%),
    var(--bg-page);
}
[data-theme="light"] body {
  /* Base is a soft cool grey, NOT pure white: the payment card is white, and on a white page its
     right/top edges dissolved into the background. A step of grey lets the card read as a distinct
     lifted surface. The red wash still sits on top. */
  background:
    linear-gradient(to bottom, rgba(255,0,8,.055) 0%, rgba(255,0,8,.05) 15%, rgba(255,0,8,.026) 38%, rgba(255,0,8,0) 66%),
    #eceef2;
}
.themesw__opt[aria-checked="true"] { color: var(--text-primary); }

/* Commerce Bank's form has a FIXED width (~465px of fields, ~672px at our 1.2 zoom) that we
   can't change cross-origin. So instead of letting the extra width become a void: the form
   column is sized snug to the form, the rail takes the rest, and the whole pair is capped and
   centred. On big screens we scale the form UP (below) rather than widen the gutters. */
/* grid-template-rows: minmax(0,1fr) is REQUIRED — without it the single grid row auto-sizes to
   its tallest content and overflows the (shrunk) container, so the card never gets told to
   shrink and the page scrolls. This pins the row to the container height and lets both cells
   shrink. */
.pay-split { display: grid; grid-template-columns: minmax(360px, 40%) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); flex: 1 1 auto; min-height: 0; transition: opacity .16s ease; }
.pay-split.is-swapping { opacity: 0; }

/* ==================== LEFT: brand / trust / contact ==================== */
/* min-height:0 + overflow-y:auto — on a viewport too short for the full rail, the RAIL scrolls
   inside itself rather than making the whole page scroll and shoving the footer off-screen. */
.brandside {
  background: transparent;
  display: flex; align-items: stretch; min-height: 0; overflow-y: auto; overflow-x: hidden;
  /* Scrollbar HIDDEN. When the rail is a few px too tall for the viewport, `auto` drew a thin
     scrollbar pinned to the rail's right edge — a hard vertical line right at the column boundary
     that read as a seam splitting the page. The rail is a brand panel, not a scroll region, so the
     bar is removed; the height-scaling tiers below keep the content fitting so nothing meaningful
     is ever cut. */
  scrollbar-width: none; -ms-overflow-style: none;
}
.brandside::-webkit-scrollbar { width: 0; height: 0; }
.brandside .neon-breathe { z-index: 0; }
/* The rail has NO glow of its own. It used to carry a left-anchored radial wash, but that radial's
   circular fade edge became a VISIBLE curved cut-off line where it met the page's top-centre body
   glow — obvious on smaller viewports where the radius compresses. One glow source only (the body
   wash) means the two can never intersect, so the bleed is smooth everywhere. The far-left
   neon-breathe accent stays; it fades horizontally and does not form a ring. */
.brandside { background: transparent; }
/* Rail content is biased toward the centre (right side of the rail) rather than dead-centre of
   the panel, so it sits closer to the form instead of hugging the far left edge. */
.brandside__in { position: relative; z-index: 1; width: 100%; max-width: 560px; margin-left: auto; margin-right: clamp(20px, 3.6vw, 76px); padding: clamp(16px, 2.6vh, 26px) clamp(30px, 2.4vw, 56px); display: flex; flex-direction: column; min-height: 100%; }
/* keep logo pinned top + tagline pinned bottom; vertically centre the hero/trust/contact block
   so the rail's whitespace reads as balanced breathing room, not a gap. */
/* content flows from just under the header (no big centred gap); rail fills to the footer */
.brandside__body { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: flex-start; }

/* Logo centred alone at the top; the theme switch lives at the bottom of the rail, centred under
   the contact card. */
.brandside__top { display: flex; flex-direction: column; align-items: center; margin-bottom: clamp(10px, 2.35vh, var(--sp-6)); }
/* Glowing red divider under the logo — a small echo of the footer bar, bookending the rail and
   separating the brand mark from the message. align-self centres it in the flex column. */
.brandsep { align-self: center; height: 2px; width: min(200px, 52%); margin: 0 0 clamp(10px, 2.35vh, var(--sp-6)); background: linear-gradient(90deg, transparent, var(--red-light) 50%, transparent); filter: drop-shadow(0 0 4px var(--red-glow-50)) drop-shadow(0 0 11px var(--red-glow-40)); }
/* Theme switch pinned bottom-right for TESTING. Final roll-out: remove this UI and just follow the
   OS theme (prefers-color-scheme) — the page already supports 'system'. */
#themeSwitch { position: fixed; bottom: 18px; right: 18px; z-index: 50; }
.brandside__logolink { display: inline-flex; border-radius: var(--r-sm); }
.brandside__logolink:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--red-glow-20); }
/* Stacked lockup (flame centred over the wordmark) — inherently balanced when centred, no nudge. */
.brandside__logo { height: clamp(64px, 9.8vh, 102px); width: auto; display: block; filter: drop-shadow(0 0 5px var(--red-glow-40)) drop-shadow(0 0 18px var(--red-glow-30)); }

.hero__eyebrow { font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-eyebrow); color: var(--red-light); margin-bottom: 12px; text-shadow: 0 0 14px var(--red-glow-40); }
.hero h1 { font-size: clamp(34px, 2.6vw, 46px); font-weight: 680; letter-spacing: -.03em; line-height: 1.04; margin: 0 0 16px; }
.hero__sub { font-size: var(--fs-lg); color: var(--text-secondary); line-height: var(--lh-snug); margin: 0 0 clamp(10px, 2.1vh, 22px); }

/* Centre the hero and the contact card. The trust list stays left-aligned — icon + wrapping
   sentence rows read wrong centred. */
.hero { text-align: center; }
.contact { text-align: center; }
.contact__actions { align-items: center; }
.contact__row { justify-content: center; }
.contact__third { text-align: center; }

/* Commerce Bank brand green pill — sampled from their own UI:
   #0D6E4F (their primary button/nav green) and #72B64F (their logo accent). */
.ep--commerce { background: rgba(13,110,79,.10); border-color: rgba(13,110,79,.32); color: #0B6247; }
[data-theme="dark"] .ep--commerce { background: rgba(114,182,79,.13); border-color: rgba(114,182,79,.36); color: #86C866; }

.trust { list-style: none; margin: 0 0 clamp(10px, 2.35vh, var(--sp-6)); padding: 0; display: flex; flex-direction: column; gap: 2px; }
.trust li { display: flex; align-items: center; gap: var(--sp-4); padding: 14px 0; border-bottom: 1px solid var(--hairline-faint); font-size: var(--fs-md); color: var(--text-secondary); line-height: var(--lh-snug); }
.trust li:last-child { border-bottom: 0; }
/* COLOR SYSTEM — every colour means exactly one thing on this page:
     red    = Springfield Sign (brand chrome)
     green  = Commerce Bank (the processor), everywhere it appears
     blue   = security / encryption
     amber  = fees & refunds
     neutral= raw contact data only                                                     */
.trust .ic { flex: none; width: 38px; height: 38px; border-radius: var(--r-md); display: grid; place-items: center; border: 1px solid; box-shadow: 0 0 11px -3px currentColor; }
.trust .ic svg { width: 18px; height: 18px; }
/* blue = security */
.ic--secure { background: var(--order-bg); color: var(--order-text); border-color: var(--order-bd); }
/* green = Commerce Bank, matching the .ep--commerce pills exactly */
.ic--commerce { background: rgba(13,110,79,.10); color: #0B6247; border-color: rgba(13,110,79,.32); }
[data-theme="dark"] .ic--commerce { background: rgba(114,182,79,.13); color: #86C866; border-color: rgba(114,182,79,.36); }
/* red = Springfield Sign (the statement descriptor is about our name) */
.ic--brand { background: var(--red-glow-10); color: var(--red-light); border-color: var(--border-red-subtle); }

.note { display: flex; gap: 10px; align-items: flex-start; padding: 13px 15px; border-radius: var(--r-md); background: rgba(240,169,57,.08); border: 1px solid rgba(240,169,57,.22); margin-bottom: var(--sp-4); }
.note svg { flex: none; width: 15px; height: 15px; color: var(--yellow-text); margin-top: 1px; }
.note span { font-size: var(--fs-sm); color: var(--text-tertiary); line-height: var(--lh-snug); }

/* contact — elevated tile with real .ep action pills */
/* margin-top:auto anchors the contact card to the BOTTOM of the rail. When the payment card is
   scaled down on a short screen the rail has slack below it; this pushes the contact box down so the
   rail bottom and the card bottom line up instead of leaving dead space under the rail. At tall
   viewports the rail is the taller column (no slack) so this has no effect. */
.contact { padding: clamp(12px, 1.95vh, var(--sp-5)); border-radius: var(--r-lg); border: 1px solid var(--hairline); background: var(--bg-card-elevated); box-shadow: var(--shadow-pop); margin-top: auto; }
.contact__h { font-size: var(--fs-sm); font-weight: 700; color: var(--text-primary); margin-bottom: 7px; }
/* who you're reaching, as a structured eyebrow rather than loose plaintext */
.contact__who { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-eyebrow); color: var(--text-faint); margin-bottom: var(--sp-4); }
.contact__actions { display: flex; flex-direction: column; gap: 10px; }
.contact__row { display: flex; flex-wrap: wrap; gap: 10px; }
/* the processor is a separate company — set apart from Springfield Sign's own contacts */
.contact__third { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px dashed var(--border-neutral); }
.contact__third-lbl { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-wide); color: var(--text-faint); margin-bottom: 9px; line-height: 1.5; }

/* Springfield Sign tagline — centred footer that blends into the page (no bordered bar). Instead
   of a hard hairline, a soft red "neon" divider line that fades at the edges + a faint red rise,
   so it reads as part of the Neon Glow environment rather than a separate strip. */
/* No background wash on the footer itself: the ONLY glow is the bar's halo (drop-shadow below),
   which blooms symmetrically across the footer's top edge, so there is no brightness step / line
   where it meets the panel above. */
.tagline { flex: none; margin-top: clamp(14px, 4.2vh, 44px); position: relative; display: flex; align-items: center; justify-content: center; width: 100%; padding: 15px 24px 16px; background: transparent; font-size: 11px; text-transform: lowercase; color: var(--text-dim); letter-spacing: .08em; }
/* Glowing neon bar across the top of the footer. */
/* Footer glow = the neon LINE itself glows. drop-shadow follows the line's own shape, so it
   blooms above and below the bar and fades out at the ends — no blob behind the text. Nothing is
   positioned outside the page, so there's no stray overflow (that was the tiny scroll + the black
   canvas line at the very bottom). */
.tagline::after { content: ''; position: absolute; top: 0; left: 50%; transform: translateX(-50%); width: min(760px, 66%); height: 2px; background: linear-gradient(90deg, transparent, var(--red-glow-40) 16%, var(--red-light) 50%, var(--red-glow-40) 84%, transparent); filter: drop-shadow(0 0 3px var(--red-light)) drop-shadow(0 0 9px var(--red-glow-50)) drop-shadow(0 0 20px var(--red-glow-30)); }
/* Light: the dark theme's triple bloom read as a muddy pink cloud on the pale page. Tighter, dimmer
   feather so it stays a crisp accent line instead of a smear. */
[data-theme="light"] .tagline::after { height: 1px; width: min(620px, 58%); filter: drop-shadow(0 0 2px var(--red-glow-40)) drop-shadow(0 0 5px var(--red-glow-20)); opacity: .7; }
.tagline span + span { margin-left: 14px; padding-left: 14px; border-left: 1px solid var(--border-neutral); }
.contact__actions .ep { text-decoration: none; }
.contact__actions .ep:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--red-glow-20), 0 0 16px -5px currentColor; }
.themesw__opt:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--red-glow-20); border-radius: var(--r-pill); }

/* ==================== RIGHT: the payment form ==================== */
/* Centre the form card vertically against the rail. The form is the shorter column, so top-
   aligning it left dead space beneath it and read as sitting too high; centring balances the two. */
/* Flex COLUMN so the card can be sized to fill whatever vertical space is left after the tabs,
   capped at its natural 812px. overflow VISIBLE so the card's red glow is never clipped (padding
   gives it clearance). min-height:0 lets the whole chain shrink on short viewports instead of
   forcing a page scroll. */
/* Card is aligned to the START of its column (nearer the rail) instead of centred in it. Centred,
   on a wide screen it drifted to the right edge — big empty gap between rail and card, and a left
   page margin far bigger than the right. Start-aligned it sits next to the rail, tightening the
   centre and evening the outer margins. Vertical centring (justify-content) is unchanged. The
   account pane overrides align-items to stretch, so this only affects the pay pane. */
/* Small vertical padding: the card sits close under the tab bar so there is no wide dark gap above
   the embed for a "bar" to appear in. Horizontal padding unchanged (that sets the rail/card gap). */
.formside { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; min-height: 0; overflow: visible; padding: clamp(8px, 1.4vh, 16px) clamp(24px, 3vw, 72px); }
/* No solid base colour: the formside is transparent so the body's top glow flows down through it
   (in the strip above the card) instead of being masked off on the right. Its own top-right radial
   still layers on for depth. The card/pane inside is opaque, so only the surround shows the glow. */
/* No own glow: the single body wash lights the form side symmetrically. Its former top-right radial
   made the right half redder than the left, which read as a lopsided, seam-y field. Transparent, so
   the body glow shows through evenly. */
.formside { background: transparent; }
.formside__in { width: 100%; max-width: 1000px; flex: 1 1 auto; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr); }

/* background:#fff — the Commerce form is white, so the card behind it is white too. It used to be
   the dark theme card colour; where the white form's clipped rounded corners did not perfectly meet
   the card's rounded corners, that dark background showed through as dark notches behind the embed
   (the "black box in the corners"). White means nothing dark can ever peek out. */
.paycard { width: 100%; border: 1px solid var(--border-neutral); border-radius: var(--r-xl); overflow: hidden; background: #fff; box-shadow: var(--shadow-float); flex: 1 1 auto; min-height: 0; max-height: 812px; display: flex; flex-direction: column; }
/* The form sits on a red back glow, with a glowing red edge, so it reads as the lit focal point. */
/* The card sits in the page's red body glow now, so it no longer needs its own hard red ring/border
   — that 1px red outline doubled with the wash behind it and looked like a weird bright line along
   the top edge. Neutral thin border + a SOFT, diffuse outer red glow only: the halo reads as ambient
   light, not an outline, and there is no hard seam at the top. */
/* NO dark drop-shadow (var(--shadow-float)) any more: its dark blur haloed the card and, against
   the top glow, read as a dark bar hugging the card's top edge. The card lifts off the page purely
   with a soft RED glow now (less negative spread so it reaches up and fills the gap above the card
   with red instead of dark) plus the thin border. */
/* A soft but BRIGHT halo hugging the card (positive spread so it starts bright right AT the edge,
   then blurs out) — this lights the rounded-corner notch and the immediate surround red, so there
   is no dim/dark gap around the white card. Diffuse, not a hard ring. */
/* Light: a REAL lift shadow (neutral) + hairline so the white card reads as a raised surface on the
   grey page, plus a soft red glow for the brand accent. The old red-only glow gave it no edge. */
[data-theme="light"] .paycard { border-color: rgba(0,0,0,.10); box-shadow: 0 12px 34px -8px rgba(24,24,40,.20), 0 2px 8px rgba(24,24,40,.08), 0 0 0 1px rgba(0,0,0,.03), 0 0 46px -12px rgba(255,0,8,.16); }
[data-theme="dark"] .paycard { border-color: rgba(255,255,255,.09); box-shadow: 0 0 30px 4px rgba(255,0,8,.42), 0 0 90px -10px rgba(255,0,8,.30); }

/* WIDE-but-SHORT desktop (the XPS): the Commerce form is in TWO columns (>1150px wide) and needs
   its full ~812px height. If the viewport is too short and the card shrinks below that, Commerce
   makes each COLUMN scroll on its own — the "two columns with individual scrollbars" that did not
   size nicely. Here we pin the card to the form's height and top-align it so the PAGE scrolls once
   to reveal the whole form, instead of the form scrolling in pieces inside a squashed card.
   Gate at 985px, NOT 940: the Commerce form is ~810px and the card only reaches its full 812px in
   the fit-to-viewport model once the viewport is ~977px+ tall. Between 941 and 976 the old 940 gate
   left the card fit-shrunk to ~778-808px — just under the form — so the columns inner-scrolled again.
   Pinning up through 985 keeps the whole band on the clean single page-scroll. Above 985 the full
   card fits centred with no scroll and no inner-scroll, so the fit-to-viewport model stays. */
@media (min-width: 1151px) and (max-height: 985px) {
  /* Switch OFF the fit-to-viewport model here. Normally the grid row is minmax(0,1fr) and the card
     flex-shrinks to fit, which is what squashed it. Make the row content-sized, give the card its
     full height, top-align it, and let the whole PAGE scroll from the top. */
  /* flex:0 0 auto is the KEY line: without it the pay-split flex-SHRINKS to fit the viewport, the
     footer rides up with it, and the fixed-height card overflows DOWN over the footer. Content-sized
     and non-shrinking, the pay-split pushes the footer below the card and the whole page scrolls. */
  .pay-split { grid-template-rows: auto; align-items: center; flex: 0 0 auto; min-height: auto; }
  .paycard { flex: 0 0 auto; min-height: 812px; max-height: none; }
  .formside { justify-content: center; }
  .brandside { overflow: visible; }
  /* Reclaim vertical space above the card. On a short laptop screen the 812px Commerce form is
     already taller than the page area, so every pixel of top chrome pushes the Process button
     further below the fold. Trim the tab-bar and form padding so the card starts as high as
     possible and the scroll needed to reach the bottom is minimal. */
  .paytabs { padding-top: 3px; }
  /* Real breathing room ABOVE the card (gap below the tab bar) and BELOW it (gap above the footer).
     SYMMETRIC top/bottom padding so the card sits centred in its column and shares the exact same
     horizontal centre line as the brand rail (both cells are centred in the row). */
  .formside { padding-top: 20px; padding-bottom: 20px; }
  .tagline { margin-top: 28px; padding: 8px 24px 12px; }
  /* The PAGE now scrolls here (it doesn't on tall desktop). The tab bar is transparent, so if it
     stays sticky the scrolled form ghosts up behind it and the red indicator line floats across the
     fields. Make it scroll away with the page instead — position:relative keeps it as the
     positioning context for the sliding indicator and the top-left site pill, minus the pinning.
     !important because the base `.paytabs { position: sticky }` sits LATER in this file (equal
     specificity would lose to source order) AND the shared attache.css carries `.tabs` sticky rules
     that could match if the DOM nesting ever changes. This one override must simply win. */
  .paytabs { position: relative !important; }
}

.paycard__head { display: flex; align-items: center; gap: var(--sp-3); padding: 13px var(--sp-5); border-bottom: 1px solid var(--hairline); background: var(--bg-card); }
.paycard__head .lock { width: 16px; height: 16px; color: var(--green-text); flex: none; }
.paycard__head .t { font-size: var(--fs-base); font-weight: 600; }
.paycard__head .grow { flex: 1; }

/* padding:0 — the white Commerce form fills the card edge-to-edge. The old padding left a strip of
   the dark card body showing around the form, and that strip across the TOP read as a "bar" above
   the embed. The card is now just the form itself: rounded corners (paycard clips), a neutral
   border, and the soft outer glow. */
.paycard__body { padding: 0; background: transparent; flex: 1 1 auto; min-height: 0; display: flex; }

/* The Commerce Bank form is responsive: at ~900px+ it lays out in TWO columns with normal-size
   fields, which fills the width without scaling anything up. We give it real width (formside__in
   max-width) and set the iframe height to the form's content height in that layout. Its footer
   pins to the bottom, so the height is tuned per layout (2-col wide vs 1-col stacked). If
   Commerce changes their fields, re-measure these heights. Measured 2026-07-20. */
/* The plate fills the card body via flex (no fixed height). The card is capped at 812px (its
   natural 2-col content height, measured 2026-07-20) and shrinks below that on short viewports;
   when it shrinks, the Commerce form scrolls INSIDE its own iframe (button stays reachable)
   instead of the whole page scrolling. */
/* border-radius:0 — the paycard (overflow:hidden, 18px radius) does the corner rounding now. The
   plate had its own smaller radius, which left a sliver of dark card poking through at each corner
   once the padding was removed. */
.payplate {
  position: relative; overflow: hidden; background: #fff; border-radius: 0;
  width: 100%; flex: 1 1 auto; min-height: 0;
}
.payplate iframe { display: block; border: 0; width: 100%; height: 100%; }
/* Dark theme: the Commerce form is light-only. With the padding removed it fills the card, so the
   old "lifted document" inset shadow (which needed the dark border around it to read) is gone —
   the card's own border + outer glow provide the lift. */

.formcap { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: var(--sp-5); font-size: var(--fs-sm); color: var(--text-tertiary); }
.formcap svg { width: 14px; height: 14px; }

/* Tabbed form panel: centre the Attaché-style tabs over the card. */
/* Page-level tab bar (it lives outside .pay-split — see the note in index.html). Because it is
   not inside the grid whose tracks collapse for My Account, it holds its position across both
   panes. That is what makes the indicator slide cleanly instead of chasing a moving bar. */
/* Sticky so the tabs stay reachable instead of scrolling off. Needs an opaque background or
   the page content shows through underneath it. */
/* position: sticky pins the bar to the top on scroll AND acts as the positioning context for the
   sliding indicator below (one rule, not the two competing ones that were here — a later
   position:relative was silently overriding the sticky, which is why it never locked). Opaque
   page-coloured background so scrolled content doesn't show through under it. */
/* The glow is a SINGLE top-centre wash painted on <body> (see the body rules below), flowing down
   behind everything. The bar is FULLY TRANSPARENT — no fill, no backdrop-filter, no mask — so that
   one glow passes straight through it with zero alteration and reads as one continuous field. An
   earlier backdrop-filter frosted the glow into a faint rectangle around the tabs (a visible seam),
   which is exactly what we do not want. On mobile, where the page scrolls under the sticky bar, a
   light scrim is re-added below for legibility (desktop does not scroll, so it needs nothing). */
.paytabs { flex: none; justify-content: center; margin: 0; padding: 10px 0 0; border-bottom: 0;
  position: sticky; top: 0; z-index: 60; background: transparent; }
/* Mobile only: the pay pane scrolls under the sticky bar, so a blur (no opaque fill, no mask) keeps
   the tab labels legible over whatever scrolls past. Desktop does not scroll and stays perfectly
   transparent so the glow reads as one continuous field. */
@media (max-width: 1150px) {
  .paytabs { -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); }
}

/* Back to the main site. Absolutely positioned inside the sticky bar so it holds the top-RIGHT
   corner without disturbing the centred tabs or the indicator's measurements. */
.sitelink {
  position: absolute; right: clamp(10px, 1.6vw, 22px); top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; gap: 7px; z-index: 2;
  padding: 6px 12px 6px 9px; border-radius: var(--r-pill);
  border: 1px solid var(--border-neutral); background: var(--bg-card);
  font-size: var(--fs-sm); font-weight: 600; color: var(--text-secondary);
  text-decoration: none; white-space: nowrap;
  transition: color .18s, border-color .18s, box-shadow .18s, transform .18s;
}
.sitelink svg { width: 14px; height: 14px; flex: none; transition: transform .18s; }
/* The SSG favicon flame mark, so the link is unmistakably OURS (a home icon read generic). */
.sitelink__ico { width: 18px; height: 18px; flex: none; display: block; object-fit: contain; }
/* Narrow screens: the tab bar fills nearly the full width, so the full-width pill sat on top of
   the first tab and swallowed its taps. Collapse to the favicon alone, which clears the tabs. */
@media (max-width: 820px) {
  .sitelink { padding: 6px; gap: 0; right: 8px; }
  .sitelink__txt { display: none; }
}
/* On the narrowest phones the two tabs span the full width and would run under the pill, which
   ate taps on "My Account". Reserve a lane on the RIGHT for it so the tabs can never reach that far. */
@media (max-width: 520px) {
  .paytabs { padding-right: 46px; padding-left: 10px; }
}
.sitelink:hover { color: var(--text-primary); border-color: var(--border-red-subtle); box-shadow: 0 0 18px -6px var(--red-glow-40); }
.sitelink:hover svg { transform: translateX(-2px); }
.sitelink:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--red-glow-20); }

/* Reload-to-login control for the Commerce portal. Sits above the frame, quiet by default so it
   never competes with the portal's own UI. */
/* FLOATS over the portal iframe's top-right corner, not in a strip above it. An earlier version
   put it in its own flow row, which opened a black band between the glowing tab bar and the portal
   (breaking the glow) and read as a "weird spot". As an absolute overlay it costs no layout height,
   so the portal fills right up under the tab bar and the glow stays continuous. The account tabpane
   is the positioning context (position:relative, set below). */
.acctbar { position: absolute; top: 14px; right: 16px; z-index: 6; }
/* [hidden] must beat the block above (same specificity, so state it explicitly). Hidden until
   pay.js detects the Commerce sign-up screen. */
.acctbar[hidden] { display: none; }
.acctbar__btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: var(--r-pill);
  border: 1px solid var(--border-neutral); background: var(--bg-card);
  font-family: inherit; font-size: var(--fs-sm); font-weight: 600; color: var(--text-secondary);
  cursor: pointer; transition: color .18s, border-color .18s, box-shadow .18s;
  box-shadow: 0 6px 20px -8px rgba(0,0,0,.6), 0 0 0 1px rgba(0,0,0,.04);   /* legible over the light portal */
}
.acctbar__btn svg { width: 14px; height: 14px; flex: none; }
.acctbar__btn:hover { color: var(--text-primary); border-color: var(--border-red-subtle); box-shadow: 0 0 20px -5px var(--red-glow-40); }
.acctbar__btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--red-glow-20); }

/* Sliding tab indicator. Attaché draws the active underline as a per-tab ::after that fades in
   and out, which reads as two separate bars blinking. Here ONE bar physically travels between
   the tabs, so switching panes is a single continuous motion. */
.paytabs .tab::after { display: none !important; }
.paytabs__ind {
  position: absolute; bottom: -1px; left: 0; height: 2px; width: 0;
  background: var(--red-bright); border-radius: 2px 2px 0 0; pointer-events: none;
  box-shadow: 0 0 10px 1px var(--red-bright), 0 4px 16px 0 var(--red-light), 0 8px 26px -2px var(--red-light);
  transition: transform .34s cubic-bezier(.4, 0, .2, 1), width .34s cubic-bezier(.4, 0, .2, 1);
}
@media (prefers-reduced-motion: reduce) { .paytabs__ind, .pay-split { transition: none; } }
/* The active pane fills the space under the tabs and vertically centres the card, so the card
   grows to fill a tall viewport (capped 812) and shrinks on a short one — no page scroll. */
/* BOTH panes are always rendered and stacked in the same grid cell. The inactive one is only
   hidden by opacity, so it keeps real dimensions and can fully boot AND paint in the background.
   With display:none the Commerce SPA gets zero dimensions and defers painting, so switching tabs
   made it lay out from scratch — that was the grey flash on switch. Now the switch is instant. */
/* background TRANSPARENT — this pane is the same rectangle as the rounded card that fills it, so a
   solid dark (#0b0b0f) pane background showed through at the card's rounded corners as dark square
   notches: THE "black box behind the embed". Transparent means the body glow sits behind the card
   instead. */
.formside__in .tabpane { grid-area: 1 / 1; position: relative; display: flex; flex-direction: column; min-height: 0; justify-content: center; opacity: 0; pointer-events: none; z-index: 1; background: transparent; }
.formside__in .tabpane.on { opacity: 1; pointer-events: auto; z-index: 2; }

/* "My Account" = the customer portal, which is a full app (own sidebar, logo, contact, dark theme).
   In this mode we hide our rail and let it fill the frame full-bleed. */
/* Collapse the rail track to 0 rather than swapping to a single column — same end state, but
   grid-template-columns interpolates between two tracks, so the rail slides closed and the form
   column (and the tab bar with it) glides to full-bleed instead of snapping. */
.pay-split.is-account { grid-template-columns: 0px minmax(0, 1fr); }
/* opacity:0 (NOT display:none — that drops it as a grid item and the formside auto-places into the
   0px first track, rendering the portal 0px wide). overflow:hidden + min-height:0 clip the rail's
   0-width-wrapped content so it can't balloon and add a phantom scrollbar. */
.pay-split.is-account .brandside { opacity: 0; pointer-events: none; overflow: hidden; min-height: 0; }
/* Crossfade on tab switch. The layout swap (rail track -> 0, form column -> full bleed) happens
   INSTANTLY at the midpoint, while every animated element is at opacity 0, so the reflow is
   never seen. Animating the grid tracks instead was the glitchy jumping: the tracks moved while
   content was still visible and the tab bar rode along with them. */


.formside__in .tabpane.on { animation: none; }
.pay-split.is-account .formside { padding: clamp(10px, 1.4vw, 20px); align-items: stretch; }
.pay-split.is-account .formside__in { max-width: 2400px; }

/* Pre-paint tab restore. pay.js reads the URL hash in <head> and stamps it on <html> before the
   body paints, so refreshing on #account lands straight on the portal instead of flashing the
   one-time payment form for a frame first. These mirror the .is-account rules above. */
html[data-pane="account"] .pay-split { grid-template-columns: 0px minmax(0, 1fr); }
html[data-pane="account"] .brandside { opacity: 0; pointer-events: none; overflow: hidden; min-height: 0; }
html[data-pane="account"] .formside { padding: clamp(10px, 1.4vw, 20px); align-items: stretch; }
html[data-pane="account"] .formside__in { max-width: 2400px; }
html[data-pane="account"] .formside__in .tabpane[data-pane="pay"] { opacity: 0; pointer-events: none; }
html[data-pane="account"] .formside__in .tabpane[data-pane="account"] { opacity: 1; pointer-events: auto; }
/* Flex-filled like the pay card, so the portal takes the space left above the footer instead of
   a fixed 100vh calc that would push the footer off the bottom. */
/* Two stacked frames (live + pre-warmed spare) share one box, so position:relative here and each
   frame absolutely fills it. Only .is-live is visible and interactive; the spare sits behind,
   inert, parked on login for an instant swap. */
/* The account portal is full-bleed and must fill the space tab-to-footer. The one-time-payment fit
   model content-sizes the split to the 812px card and centres it; on this pane that squeezed the
   portal to 812px and floated it with a big gap above. Restore the fill model here, and drop the pay
   card out of the layout so it can't force the row height. */
.pay-split.is-account, html[data-pane="account"] .pay-split { flex: 1 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); align-items: stretch; }
.pay-split.is-account .formside, html[data-pane="account"] .formside { justify-content: stretch; }
.pay-split.is-account .formside__in .tabpane[data-pane="pay"],
html[data-pane="account"] .formside__in .tabpane[data-pane="pay"] { display: none; }

.accountframe { position: relative; width: 100%; flex: 1 1 auto; min-height: 0; }
/* Desktop: pin the portal frame to the room between the tab bar and the footer with an explicit
   height. The flex chain collapsed on short viewports (the pay-pane fit rules left it unconstrained,
   so the frame ballooned and the page scrolled). A fixed calc fills the space cleanly at every height
   and, centred in its column, sits balanced between the tabs and the footer. */
@media (min-width: 1151px) {
  /* min-height so the Commerce SIGN-IN card always has room. On a short viewport (a zoomed-in TV
     browser gives a small CSS viewport) calc(100vh - 172px) fell below the login card's height and
     the form cramped/scrolled inside the frame. The floor keeps it comfortable; the page scrolls a
     little on very short screens instead, which is fine. Tall screens still fill via the calc. */
  .pay-split.is-account .accountframe,
  html[data-pane="account"] .accountframe { flex: 0 0 auto; height: calc(100vh - 172px); min-height: 600px; }
}
.accountframe__f { position: absolute; inset: 0; display: block; border: 0; width: 100%; height: 100%;
  border-radius: var(--r-lg); box-shadow: var(--shadow-float);
  visibility: hidden; pointer-events: none; z-index: 0; }
.accountframe__f.is-live { visibility: visible; pointer-events: auto; z-index: 1; }

/* ==================== responsive ==================== */

/* NARROW two-column desktop (~981–1300px). The rail column is only ~40% wide here, so its text
   wraps to more lines and the content grows tall enough to overflow. Scale the rail down so it
   fits its column without needing an internal scroll (the scrollbar is hidden, so an overflow
   would silently clip the contact card). Below 981px the layout stacks and this no longer applies. */
@media (min-width: 1151px) and (max-width: 1300px) {
  .brandside__logo { height: clamp(46px, 6.6vh, 70px); }
  .hero__eyebrow { font-size: 11px; margin-bottom: 8px; }
  .hero h1 { font-size: clamp(22px, 2.3vw, 30px); margin-bottom: 10px; }
  .hero__sub { font-size: 13px; margin-bottom: 10px; }
  .trust li { padding: 7px 0; font-size: 12.5px; }
  .trust .ic { width: 29px; height: 29px; }
  .trust .ic svg { width: 15px; height: 15px; }
  .note { padding: 10px 12px; }
  .note span { font-size: 11.5px; }
  .contact { padding: 11px; }
  .contact__who { margin-bottom: 8px; }
  .contact__actions { gap: 7px; }
  .brandsep { margin-bottom: 8px; }
  .brandside__top { margin-bottom: 8px; }
}

/* Laptops are WIDE but SHORT. Nearly every size in the rail is driven by vw or carries a generous
   px minimum, so a 1920x1080 laptop got almost the full 4K rail: oversized logo, 46px headline,
   chunky trust rows. Height is the axis that actually runs out, so scale on max-height. Gated to
   min-width:981px so this never fights the stacked mobile layout below, which wants its own sizes. */
@media (min-width: 1151px) and (max-height: 950px) {
  .brandside__logo { height: clamp(52px, 8.5vh, 78px); }
  .hero__eyebrow { font-size: 11px; margin-bottom: 9px; }
  .hero h1 { font-size: clamp(26px, 2vw, 34px); margin-bottom: 12px; }
  .hero__sub { font-size: 14px; }
  .trust li { padding: 8px 0; font-size: 13.5px; }
  .trust .ic { width: 32px; height: 32px; }
  .trust .ic svg { width: 16px; height: 16px; }
  .note { padding: 10px 13px; }
  .note span { font-size: 12px; }
  .contact { padding: 13px; }
  .contact__h { font-size: 13px; }
  .contact__who { margin-bottom: 10px; }
  .contact__third { margin-top: 12px; padding-top: 12px; }
  .brandside__in { padding-top: 14px; padding-bottom: 14px; }
}
@media (min-width: 1151px) and (max-height: 800px) {
  .brandside__logo { height: clamp(46px, 7.5vh, 62px); }
  .hero h1 { font-size: clamp(22px, 1.7vw, 28px); margin-bottom: 9px; }
  .hero__sub { font-size: 13px; }
  .trust li { padding: 5px 0; font-size: 12.5px; }
  .trust .ic { width: 28px; height: 28px; }
  .trust .ic svg { width: 15px; height: 15px; }
  .note { padding: 9px 11px; margin-bottom: 10px; }
  .note span { font-size: 11.5px; }
  .contact { padding: 11px; }
  .contact__who { margin-bottom: 8px; }
  .contact__actions { gap: 7px; }
  .contact__third { margin-top: 10px; padding-top: 10px; }
  .brandsep { margin-bottom: 8px; }
  .brandside__top { margin-bottom: 8px; }
  .brandside__in { padding-top: 10px; padding-bottom: 10px; }
  .hero__eyebrow { margin-bottom: 7px; }
}

/* 1280x720 and similar. The rail scrolls internally rather than clipping, but a visibly cut-off
   contact card reads as broken, so squeeze the last of the slack out before letting it scroll. */
@media (min-width: 1151px) and (max-height: 740px) {
  .brandside__logo { height: clamp(38px, 6.4vh, 50px); }
  .hero__eyebrow { font-size: 10px; margin-bottom: 5px; }
  .hero h1 { font-size: clamp(20px, 1.5vw, 24px); margin-bottom: 7px; }
  .hero__sub { font-size: 12.5px; margin-bottom: 8px; }
  .trust li { padding: 3px 0; font-size: 12px; }
  .trust .ic { width: 25px; height: 25px; }
  .trust .ic svg { width: 14px; height: 14px; }
  .note { padding: 8px 10px; margin-bottom: 8px; }
  .note span { font-size: 11px; }
  .contact { padding: 10px; }
  .contact__h { font-size: 12.5px; margin-bottom: 4px; }
  .contact__who { margin-bottom: 6px; }
  .contact__actions { gap: 6px; }
  .contact__third { margin-top: 8px; padding-top: 8px; }
  .brandsep { margin-bottom: 6px; }
  .brandside__top { margin-bottom: 6px; }
}

/* Stack into one column on tablet/phone. Below ~700px the Commerce form drops to a SINGLE
   column (taller), so the iframe needs more height there. */
/* The DESKTOP layout deliberately constrains everything to the viewport height so the page never
   scrolls (card flex-shrinks, form scrolls in its own frame). MOBILE is the opposite: the stacked
   layout is intentionally taller than the screen and the page scrolls normally. So every height
   cap from the desktop chain has to be undone here, or the rail gets squashed into one grid row
   and the tall single-column form gets clipped by the card's 812px cap. */
@media (max-width: 1150px) {
  /* width:100% is REQUIRED here. .pay-split is a flex item of <body>, and `margin: 0 auto`
     on a flex item cancels the default stretch, so it shrink-to-fits (it was collapsing to
     300px on a 390px screen and centring, leaving 45px dead margins either side and
     squeezing the framed app). max-width still caps it on larger screens. */
  .pay-split { grid-template-columns: 1fr; grid-template-rows: auto auto; width: 100%; max-width: 640px; margin: 0 auto; flex: 0 0 auto; min-height: 0; }
  /* NO red bottom border on the stacked rail: it drew a hard red line between the brand section and
     the form card. The card's own glow is the separator. */
  .brandside { position: static; height: auto; overflow: visible; min-height: 0; border-right: 0; border-bottom: 0; }
  .brandside__in { max-width: none; padding: 30px 28px; }
  .brandside__top { margin-bottom: 28px; }
  /* Phones have no width to spare. The desktop gutters (up to 48px a side) plus the card
     padding were squeezing the framed app hard enough to collide its own columns. Go nearly
     edge to edge. */
  .formside { min-height: 0; padding: 10px 6px; }
  .paycard__body { padding: 5px; }
  /* My Account is meant to be FULL BLEED — no gutters, no rounded card edge. */
  .pay-split.is-account .formside,
  html[data-pane="account"] .formside { padding: 0; }
  .pay-split.is-account .accountframe iframe,
  html[data-pane="account"] .accountframe iframe { border-radius: 0; box-shadow: none; }
  .formside__in { max-width: none; flex: 0 0 auto; }

  /* Mobile does NOT stack the panes. On desktop both panes share one grid cell (preloaded,
     cross-fade). On mobile that made the cell as tall as the TALLEST pane — the ~1600px payment
     form — so switching to My Account left a screen of empty space below the short portal, and
     the whole page inherited the payment form's height. Here the inactive pane is display:none
     and takes zero space, so each pane is exactly as tall as its own content. */
  .formside__in { display: block; }
  .formside__in .tabpane { grid-area: auto; opacity: 1; pointer-events: auto; display: none; }
  .formside__in .tabpane.on { display: block; }
  .paycard { max-height: none; flex: 0 0 auto; display: block; }
  /* Mobile glow, cleaned up. The left-rail accent glow (.neon-breathe) is a DESKTOP effect; stacked
     it ran down the left edge and cut off hard at the rail's bottom in a dumb spot, so it's off here.
     The rail's red bottom-border (a hard line) is gone too. The card keeps a SOFT, even red halo so
     there's still glow, but low+diffuse so it reads as ambient light, not a hard line before the form. */
  .brandside .neon-breathe { display: none; }
  [data-theme="dark"] .paycard { box-shadow: 0 8px 24px rgba(0,0,0,.5), 0 0 42px 2px rgba(255,0,8,.20); }
  [data-theme="light"] .paycard { box-shadow: 0 8px 22px rgba(24,24,40,.14), 0 0 0 1px rgba(0,0,0,.05), 0 0 34px 0 rgba(255,0,8,.08); }
  .paycard__body { flex: 0 0 auto; display: block; }
  .payplate { flex: 0 0 auto; }

  /* Payment iframe height = the form's MEASURED single-column content height, plus ~90px for the
     subtotal/surcharge/total rows that appear once an amount is entered. Measured directly with
     a real device viewport (not guessed): 600px wide -> 1347, 390 -> 1443, 360 -> 1460.
     Sized this way there is no internal scroll (so the page scrolls normally, no touch-scroll
     trap) and no dead gap above Commerce's bottom-pinned button. Re-measure if they change
     fields: load the paymentLink directly at that width and read the tallest element. */
  .payplate, .payplate iframe { height: 1440px; }

  /* Rail out of flow entirely in account mode (display:none, not opacity) so the portal isn't
     pushed down by an invisible row — that was the black nothingness above My Account. */
  .pay-split.is-account .brandside,
  html[data-pane="account"] .brandside { display: none; }
  /* CRITICAL: the desktop account rule collapses the RAIL's grid column to 0px
     (grid-template-columns: 0px minmax(0,1fr)). That rule is not viewport-scoped, so on mobile —
     where the rail is display:none rather than a collapsed column — the FORM fell into that 0px
     first column and everything inside it measured 0 wide, parked at left:205. That is why My
     Account looked blank / off to the side. Mobile must be a single full-width column. */
  .pay-split.is-account,
  html[data-pane="account"] .pay-split { grid-template-columns: 1fr; grid-template-rows: auto; }

  /* The portal is a self-contained full-height app (measured 844px = viewport, own internal
     scroll), so it gets viewport height minus the sticky tab bar, not a content-sized box.
     The frames are position:absolute now, so they contribute no height: put the explicit height
     on the CONTAINER and let the frames fill it via inset:0, or the pane collapses to nothing. */
  .accountframe { flex: 0 0 auto; height: calc(100dvh - 58px); }
  .accountframe__f { height: 100%; }
}
/* Narrower screens wrap more, so the single-column form is taller. */
@media (max-width: 430px) {
  .payplate, .payplate iframe { height: 1540px; }
}
@media (max-width: 360px) {
  .brandside__in { padding: 24px 18px; }
  .payplate, .payplate iframe { height: 1560px; }
}

/* ==================== hover glow — left pane ==================== */
/* Every item on the brand rail lights up in its OWN colour on hover: security = blue,
   Commerce Bank = green, statement/brand = red, refunds note = amber, contact pills = their
   own tint. The glow eases in, and is disabled under prefers-reduced-motion. */
.brandside__logo { transition: filter .3s ease; }
.brandside__logolink { transition: transform .2s ease; }
.brandside__logolink:hover { transform: translateY(-1px); }
.brandside__logolink:hover .brandside__logo { filter: drop-shadow(0 0 6px var(--red-glow-50)) drop-shadow(0 0 22px var(--red-glow-40)); }

.trust li { padding: clamp(6px, 1.05vh, 10px) 12px; border-radius: 12px; transition: transform .22s ease, box-shadow .3s ease, background-color .3s ease; }
.trust li .ic { transition: box-shadow .3s ease, transform .3s ease; }
.trust li:hover { transform: translateX(3px); }
.trust li:hover .ic { transform: translateY(-1px); box-shadow: 0 0 14px -2px currentColor; }
.trust li:has(.ic--secure):hover  { background: var(--order-bg); box-shadow: 0 0 22px -7px var(--order-text); }
.trust li:has(.ic--commerce):hover { background: rgba(13,110,79,.08); box-shadow: 0 0 22px -7px #0B6247; }
[data-theme="dark"] .trust li:has(.ic--commerce):hover { background: rgba(114,182,79,.10); box-shadow: 0 0 22px -7px #86C866; }
.trust li:has(.ic--brand):hover  { background: var(--red-glow-10); box-shadow: 0 0 22px -7px var(--red-light); }

.note { transition: transform .22s ease, box-shadow .3s ease, border-color .3s ease, background-color .3s ease; }
.note:hover { transform: translateY(-1px); border-color: rgba(240,169,57,.45); background: rgba(240,169,57,.12); box-shadow: 0 0 24px -7px rgba(240,169,57,.6); }

.contact { transition: transform .25s ease, box-shadow .3s ease, border-color .3s ease; }
.contact:hover { transform: translateY(-1px); border-color: var(--border-red-subtle); box-shadow: var(--shadow-pop), 0 0 30px -8px var(--red-glow-30); }
.contact .ep { transition: transform .2s ease, box-shadow .25s ease, border-color .25s ease, background-color .25s ease; }
.contact .ep:hover { transform: translateY(-1px); border-color: currentColor; box-shadow: 0 0 16px -4px currentColor; }

@media (prefers-reduced-motion: reduce) {
  .brandside__logolink, .brandside__logolink:hover, .trust li, .trust li:hover, .trust li .ic,
  .note, .note:hover, .contact .ep, .contact .ep:hover, .brandside__logo { transition: none; transform: none; }
}

/* ==================== cross-origin frame load cover ====================
   Commerce's embed is an SPA: it paints a grey overlay while it boots, which reads as a harsh
   flash inside our card. We can't touch their DOM cross-origin, so instead we hold a branded
   skeleton over the frame and only reveal it once it has actually painted.

   FAIL-SAFE IS THE POINT: on a payment page a stuck skeleton is far worse than a grey flash.
   pay.js reveals on the iframe's load event AND on an unconditional timeout, so the customer
   always reaches a usable form even if load never fires. */
.payplate, .accountframe { position: relative; }
.payplate iframe, .accountframe iframe { opacity: 0; transition: opacity .18s ease; }
.payplate.is-ready iframe, .accountframe.is-ready iframe { opacity: 1; }

.plateskel {
  position: absolute; inset: 0; z-index: 2; display: flex; gap: 26px;
  padding: 30px 26px; background: #fff; border-radius: var(--r-md);
  transition: opacity .18s ease;
}
.plateskel--acct { justify-content: center; align-items: center; background: var(--bg-card); }
.payplate.is-ready .plateskel, .accountframe.is-ready .plateskel { opacity: 0; pointer-events: none; }
.plateskel__col { flex: 1; display: flex; flex-direction: column; gap: 10px; min-width: 0; }

/* Skeleton bars. Neutral grey on white so it reads as OUR placeholder rather than a broken
   render, with a slow red-tinted sweep tying it to the Neon Glow language. */
.skl { display: block; height: 34px; border-radius: 7px; background: #eceef1; position: relative; overflow: hidden; }
.skl--sm { height: 9px; width: 38%; border-radius: 4px; }
.skl--tall { height: 150px; }
.skl::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,0,8,.09) 45%, rgba(255,0,8,.05) 55%, transparent);
  transform: translateX(-100%); animation: sklsweep 1.5s ease-in-out infinite;
}
@keyframes sklsweep { to { transform: translateX(100%); } }
[data-theme="dark"] .plateskel--acct { background: #0b0b0f; }
[data-theme="dark"] .plateskel--acct .skl { background: rgba(255,255,255,.06); }
[data-theme="dark"] .plateskel--acct .skl::after {
  background: linear-gradient(90deg, transparent, rgba(255,71,87,.10) 50%, transparent);
}
@media (prefers-reduced-motion: reduce) { .skl::after { animation: none; } }
