/* Panodock — app-only layer.
   Loaded AFTER components.css.

   This file is OURS. tokens.css and components.css are verbatim copies from
   Claude Design and get overwritten wholesale on the next design round — never
   put anything here into those two, and never put anything from here into them.

   Only three kinds of rule belong here:
     1. glue the design system assumes but does not ship (icon stroke defaults,
        the logo lockup),
     2. classes the app's JS toggles by hand that the design never saw,
     3. layout the design cannot know about (server-rendered shells, R2 media).
*/

/* ---------- one token override, and the reason for it -------------------
   Outfit ships no Vietnamese subset. The UI is English but the CONTENT is
   not: tour titles, studio names, client names and lead messages routinely
   carry Vietnamese diacritics, and a heading set in Outfit would drop those
   glyphs to whatever system-ui resolves to — a visible face change mid-word.
   Naming Inter as the first fallback keeps the drop inside the type system.
   This is app knowledge the design system could not have; tokens.css stays
   untouched so it can still be overwritten wholesale. */
:root {
  --pd-font-display: 'Outfit', 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* ---------- icon sprite glue -------------------------------------------
   icons.svg symbols carry geometry only — no stroke attributes — so every
   <use> needs these. Matches the locked spec: grid 24, stroke 1.5, round
   cap + join, currentColor. Symbols that need a fill (i-google, the dots in
   i-chat/i-warn/i-info) set fill/stroke locally and win over this. */
.pd-i {
  width: 18px; height: 18px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.pd-i--sm { width: 15px; height: 15px; }
.pd-i--lg { width: 22px; height: 22px; }
.pd-i--xl { width: 30px; height: 30px; }

/* ---------- wordmark lockup ---------------------------------------------
   Eight glyphs from logo.svg on one baseline, per Panodock Logo - Solid.
   Each glyph is wrapped in its own inline-flex span: that wrapper is what
   gives `align-items:baseline` something to align, since a bare <svg> flex
   item has no baseline of its own. wordmark() in src/index.js emits it. */
.pd-logo { display: inline-flex; align-items: baseline; flex: 0 0 auto; color: var(--pd-ink); }

/* Rotation for the animated cut. Two moves only, both linear — a camera on a
   motor does not ease into a stop — and the slit starts from its 135° rest
   angle so stopping the animation lands on the static mark. 11s and 7s are
   deliberately not multiples of each other, so the two o's never settle into
   a repeating pose. Use at 40px and up; the nav ships static. */
@keyframes pd-spin-a { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes pd-spin-b { from { transform: rotate(135deg); } to { transform: rotate(495deg); } }

/* The second move — every node breathing on a 2.6s cycle, staggered 0.3s so
   the word lights left to right. It has to be declared HERE and not inside
   logo.svg: the app references that file with an external <use>, and a
   stylesheet inside an externally referenced document does not travel with
   the cloned subtree, while an inline `animation:` shorthand on the node does.
   So the glyph names the animation and the page owns the keyframes — which
   also means prefers-reduced-motion above stops it, as the spec requires.
   Unused until port/logo.svg ships the six animated glyph variants; requested
   in that project as uploads/LOGO-ANIMATED-REQUEST.md. */
@keyframes pd-node { 0%, 100% { fill-opacity: .22; } 45% { fill-opacity: 1; } 60% { fill-opacity: .85; } }

/* ---------- Panodock credit bar ------------------------------------------
   components.css hides this under .pd-err--whitelabel but never styles it. */
.pd-poweredby {
  display: inline-flex; align-items: center; gap: 9px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--pd-ink-2);
}

/* ---------- error page chrome -------------------------------------------
   components.css ships .pd-err* (the shell, the code, the title). What it
   cannot know is the two headers: the owner's cut wears the Panodock
   wordmark, the visitor's cut wears the studio's identity so a client never
   sees infrastructure they did not sign up for. */
.pd-err-top {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  min-height: 58px; padding: 12px 22px;
  background: var(--pd-card); border-bottom: 1px solid var(--pd-line);
}
.pd-err-inner { width: 100%; max-width: 640px; margin: 0 auto; }
.pd-err-card {
  width: 100%; max-width: 400px; padding: 28px 24px;
  background: var(--pd-card); border: 1px solid var(--pd-line);
  border-radius: var(--pd-r-card); box-shadow: var(--pd-shadow-card);
}
.pd-err-foot {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 16px 22px; background: var(--pd-sunken);
  border-top: 1px solid var(--pd-line); font-size: 12.5px; color: var(--pd-ink-2);
}
/* studio identity: uploaded logo, or its initials on an ink tile */
.pd-studio-mark {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 9px;
  background: var(--pd-ink); color: #FFFFFF;
  font-family: var(--pd-font-display); font-weight: 700; font-size: 11px;
}
.pd-studio-name { font-family: var(--pd-font-display); font-weight: 600; font-size: 15px; letter-spacing: -0.01em; }

/* ==========================================================================
   ADMIN SHELL — sidebar + topbar, shared by the dashboard, settings,
   analytics and the customers table (Panodock Dashboard.dc.html).
   The wordmark sits in the SIDEBAR, not the topbar; the topbar belongs to the
   main column and carries workspace, search and account only.
   ========================================================================== */

.pd-shell { display: grid; grid-template-columns: var(--pd-sidebar) minmax(0, 1fr); min-height: 100vh; }
.pd-side {
  position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column;
  background: var(--pd-card); border-right: 1px solid var(--pd-line);
}
.pd-side-brand {
  height: var(--pd-topbar); display: flex; align-items: center;
  padding: 0 18px; border-bottom: 1px solid var(--pd-line); flex: 0 0 auto;
}
.pd-side-nav { padding: 14px 12px; display: flex; flex-direction: column; gap: 2px; overflow-y: auto; }
.pd-side-grp {
  padding: 16px 12px 6px; font-family: var(--pd-font-mono);
  font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--pd-ink-3);
}
.pd-side-foot { margin-top: auto; padding: 16px 16px 18px; border-top: 1px solid var(--pd-line); flex: 0 0 auto; }

.pd-topbar {
  position: sticky; top: 0; z-index: 20; height: var(--pd-topbar);
  display: flex; align-items: center; gap: 14px; padding: 0 24px;
  background: rgba(255, 255, 255, 0.86); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--pd-line);
}
.pd-ws {
  display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto;
  height: 32px; padding: 0 12px 0 5px; border-radius: var(--pd-r-chip);
  background: var(--pd-card); border: 1px solid var(--pd-line-strong);
  font-size: 13px; color: var(--pd-ink); cursor: pointer;
}
.pd-ws:hover { border-color: var(--pd-brand-600); }
.pd-ws-mark {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 22px; height: 22px; border-radius: 7px; background: var(--pd-ink); color: #FFFFFF;
  font-family: var(--pd-font-display); font-weight: 600; font-size: 10px; overflow: hidden;
}
.pd-searchwrap { position: relative; display: flex; align-items: center; flex: 1 1 auto; max-width: 380px; }
.pd-searchwrap > svg:first-child { position: absolute; left: 12px; pointer-events: none; color: var(--pd-ink-3); }
.pd-avatar {
  width: 32px; height: 32px; border-radius: 999px; flex: 0 0 auto; cursor: pointer;
  background: var(--pd-sunken); border: 1px solid var(--pd-line);
  font-family: var(--pd-font-display); font-weight: 600; font-size: 12px; color: var(--pd-ink-2);
}
.pd-main { padding: 28px 24px 56px; max-width: 1320px; }

/* account dropdown — <details>, so it needs no JS */
.pd-menu { position: relative; margin-left: auto; flex: 0 0 auto; }
.pd-menu > summary { list-style: none; }
.pd-menu > summary::-webkit-details-marker { display: none; }
.pd-menu-drop {
  position: absolute; top: 40px; right: 0; width: 190px; z-index: 60; padding: 6px;
  background: var(--pd-card); border: 1px solid var(--pd-line-strong);
  border-radius: var(--pd-r-field); box-shadow: var(--pd-shadow-hover);
}
.pd-menu-drop a {
  display: flex; align-items: center; gap: 9px; padding: 9px 11px;
  border-radius: 8px; font-size: 13px; color: var(--pd-ink-2); text-decoration: none;
}
.pd-menu-drop a:hover { background: var(--pd-page); color: var(--pd-ink); text-decoration: none; }
.pd-menu-drop a.danger { color: var(--pd-danger-ink); }
.pd-menu-sep { height: 1px; margin: 5px 8px; background: var(--pd-line); }

/* Below the sidebar breakpoint it becomes a horizontal scroller above the
   content — the storage block and the group headings would only add noise
   there, so they drop out. */
@media (max-width: 880px) {
  /* minmax(0,1fr), not 1fr: a grid track defaults to min-content as its floor,
     and the topbar's own min-content (workspace chip + search + status +
     avatar) is wider than a phone. With plain 1fr that floor pushed the whole
     column — and the stacked sidebar with it — past the viewport, and the page
     scrolled sideways. Measured at 360px: 479px wide before this. */
  .pd-shell { grid-template-columns: minmax(0, 1fr); }
  .pd-shell > * { min-width: 0; }
  .pd-side { position: static; height: auto; border-right: 0; border-bottom: 1px solid var(--pd-line); }
  .pd-side-nav { flex-direction: row; overflow-x: auto; padding: 10px 12px; }
  .pd-side-nav .pd-nav-item { flex: 0 0 auto; }
  .pd-side-grp, .pd-side-foot { display: none; }
  .pd-main { padding: 20px 16px 48px; }
  .pd-topbar { padding: 0 16px; gap: 10px; }
  .pd-ws { min-width: 0; overflow: hidden; }
  .pd-ws, .pd-searchwrap { flex: 1 1 auto; }
  .pd-searchwrap { min-width: 0; }
}
/* below the tablet cut the workspace name is the first thing worth dropping —
   the mark still identifies it and the search needs the room more */
@media (max-width: 560px) {
  .pd-ws { flex: 0 0 auto; font-size: 0; padding: 0 6px 0 5px; }
  .pd-ws .pd-ws-mark { font-size: 10px; }
  .pd-ws .pd-i { font-size: initial; }
}

/* ==========================================================================
   TOUR TILE
   The markup is built by client JS as strings, and .card / .thumb / .out /
   .list-mode are names that JS queries by hand — renaming them would mean
   rewriting handlers for no gain. So the class names stay and the design
   values live here. New markup also carries .pd-card / .pd-tile so the two
   systems compose rather than fight.
   ========================================================================== */

.pd-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(292px, 1fr)); gap: 14px; margin-top: 14px; }
.pd-grid .card { display: flex; flex-direction: column; overflow: hidden; }
.pd-grid .card .thumb {
  position: relative; display: block; aspect-ratio: 16/10;
  background: linear-gradient(145deg, #2b3750, #151922) center/cover no-repeat;
}
.pd-grid .card .thumb .ph {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--pd-font-mono); font-size: 22px; color: rgba(255, 255, 255, 0.22);
}
.pd-grid .card .vbadge, .card .vischip {
  position: absolute; top: 10px; display: inline-flex; align-items: center; gap: 5px;
  height: 23px; padding: 0 9px; border-radius: var(--pd-r-chip);
  background: rgba(12, 12, 18, 0.62); backdrop-filter: blur(6px);
  font-family: var(--pd-font-mono); font-size: 9.5px; color: #FFFFFF;
}
.pd-grid .card .vbadge { left: 10px; }
.pd-grid .card .vischip { right: 10px; letter-spacing: 0.1em; }
.pd-grid .card .vischip .d { width: 5px; height: 5px; border-radius: 999px; background: var(--pd-live); }
.pd-grid .card .body { padding: 14px 16px 16px; display: flex; flex-direction: column; flex: 1 1 auto; }
.pd-grid .card .thead { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.pd-grid .card .title {
  font-family: var(--pd-font-display); font-weight: 600; font-size: 15.5px;
  letter-spacing: -0.01em; color: var(--pd-ink); text-decoration: none;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pd-grid .card .title:hover { color: var(--pd-brand-700); text-decoration: underline; }
.pd-grid .card .tag {
  flex: 0 0 auto; font-family: var(--pd-font-mono); font-size: 9px; letter-spacing: 0.06em;
  border-radius: var(--pd-r-chip); padding: 2px 8px;
}
.pd-grid .card .tag.new { color: var(--pd-brand-700); background: var(--pd-brand-tint); }
.pd-grid .card .tag.legacy { color: var(--pd-ink-2); background: var(--pd-sunken); }
.pd-grid .card .starbtn {
  flex: 0 0 auto; background: none; border: 0; cursor: pointer; line-height: 0;
  padding: 0 2px; color: var(--pd-ink-4); display: inline-flex; align-items: center;
}
.pd-grid .card .starbtn.on, .card .starbtn:hover { color: #F5A623; }
.pd-grid .card .meta {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-top: 6px;
  font-family: var(--pd-font-mono); font-size: 10.5px;
  letter-spacing: var(--pd-meta-track); color: var(--pd-ink-3);
}
.pd-grid .card .meta .dot { color: var(--pd-ink-4); }
.pd-grid .card .aiwrap { display: flex; gap: 6px; margin-top: 12px; flex-wrap: wrap; }
.pd-grid .card .aichip {
  display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px;
  border-radius: var(--pd-r-chip); font-size: 11.5px;
}
.pd-grid .card .aichip.on { background: rgba(37, 99, 235, 0.08); color: var(--pd-brand-700); }
.pd-grid .card .aichip.off { background: var(--pd-page); color: var(--pd-ink-2); }
.pd-grid .card .acts {
  display: flex; align-items: center; gap: 6px; margin-top: auto;
  padding-top: 13px; border-top: 1px solid var(--pd-line);
}
.pd-grid .card .acts > .pd-btn { height: 32px; font-size: 12.5px; }
.pd-grid .card .acts > .pd-btn--primary { flex: 1 1 auto; }
.pd-grid .card .out { flex-basis: 100%; margin-top: 8px; font-family: var(--pd-font-mono); font-size: 11.5px; }

/* list mode: same card, laid on its side. JS toggles .list-mode on the grid. */
.pd-grid.list-mode { grid-template-columns: 1fr; gap: 8px; }
.pd-grid.list-mode .card { flex-direction: row; align-items: center; }
.pd-grid.list-mode .card:hover { transform: none; }
.pd-grid.list-mode .thumb { width: 116px; height: 70px; aspect-ratio: auto; flex: 0 0 auto; }
.pd-grid.list-mode .body { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 14px; padding: 10px 16px; }
.pd-grid.list-mode .thead { flex: 1 1 180px; min-width: 150px; }
.pd-grid.list-mode .meta, .list-mode .aiwrap { margin: 0; flex: 0 0 auto; }
.pd-grid.list-mode .acts { margin: 0; padding-top: 0; border-top: 0; flex: 0 0 auto; }
.pd-grid.list-mode .acts > .pd-btn--primary { flex: 0 0 auto; }
@media (max-width: 760px) {
  .list-mode .card { flex-direction: column; align-items: stretch; }
  .list-mode .thumb { width: 100%; height: auto; aspect-ratio: 16/10; }
}

/* the dashed "upload a tour" tile that closes the grid */
.pd-newtile {
  background: none; border: 1.5px dashed var(--pd-line-strong); border-radius: var(--pd-r-card);
  min-height: 230px; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 11px; cursor: pointer; color: var(--pd-ink-3);
  font-family: var(--pd-font-body);
}
.pd-newtile:hover { border-color: var(--pd-brand-600); color: var(--pd-brand-700); background: rgba(37, 99, 235, 0.03); }
.pd-grid.pd-grid.list-mode .pd-newtile { min-height: 96px; }

/* Only the outline star ships in the sprite, so "starred" fills it. */
.pd-grid .card .starbtn.on svg { fill: currentColor; }

/* ==========================================================================
   OVERLAYS (Panodock Modals.dc.html)
   Two kinds, and the difference is the exit. A dismissible modal has an X and
   a Cancel. A blocking overlay has one button named for what it does — an X
   reads as "dismiss and carry on", which is the wrong promise when abandoning
   the job leaves a tour with half its scenes.
   ========================================================================== */

/* .modal is toggled by JS with style.display='flex' — keep the name. */
.modal {
  display: none; position: fixed; inset: 0; z-index: 100; padding: 24px;
  background: var(--pd-scrim); backdrop-filter: blur(2px);
  align-items: center; justify-content: center;
}
.modal .pd-modal { max-height: 88vh; display: flex; flex-direction: column; }
.pd-modal-hd {
  display: flex; align-items: center; gap: 11px; flex: 0 0 auto;
  padding: 18px 22px; border-bottom: 1px solid var(--pd-line);
}
.pd-modal-hd > h2 { flex: 1 1 auto; min-width: 0; }
.pd-modal-bd { padding: 22px; overflow-y: auto; }
.pd-modal-ft {
  display: flex; justify-content: flex-end; gap: 10px; flex: 0 0 auto;
  padding: 15px 22px; border-top: 1px solid var(--pd-line); background: var(--pd-field);
}

/* blocking overlay: download + re-upload */
.pd-ov {
  display: none; position: fixed; inset: 0; z-index: 200; padding: 24px;
  background: var(--pd-scrim); backdrop-filter: blur(3px);
  align-items: center; justify-content: center;
}
.pd-ov-card {
  width: 100%; max-width: 452px; padding: 28px; background: var(--pd-card);
  border-radius: var(--pd-r-modal); box-shadow: var(--pd-shadow-modal);
}

/* phase checklist. done = check, current = spinner, later = blank slot, so
   the rows do not move as the job walks down them. */
.phrow { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--pd-ink-3); }
.phrow .ic { position: relative; width: 15px; height: 15px; flex: 0 0 auto; }
.phrow .ic svg { position: absolute; inset: 0; width: 15px; height: 15px; opacity: 0; stroke-width: 2; }
.phrow.done { color: var(--pd-ink); }
.phrow.done .ic svg { opacity: 1; color: var(--pd-brand-700); }
.phrow.now { color: var(--pd-ink-2); }
.phrow.now .ic::after {
  content: ""; position: absolute; inset: 0; border-radius: 999px;
  border: 2px solid var(--pd-sunken); border-top-color: var(--pd-brand-600);
  animation: pd-spin .9s linear infinite;
}

/* the DNS record the user has to copy into their registrar */
.pd-dns {
  display: grid; grid-template-columns: auto 1fr auto; gap: 10px 14px; align-items: center;
  margin-top: 12px; font-family: var(--pd-font-mono); font-size: 12px;
}
.pd-dns > .k { color: var(--pd-ink-3); }
.pd-dns > .v { color: var(--pd-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ==========================================================================
   ANALYTICS VOCABULARY
   Shared by three consumers — the account page, the tour's Analytics tab and
   the client-facing report — which each used to redefine it. One home now.
   ========================================================================== */

.srow { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 16px; }
.scard {
  background: var(--pd-card); border: 1px solid var(--pd-line);
  border-radius: var(--pd-r-card); padding: 16px 18px; box-shadow: var(--pd-shadow-card);
}
.scard .k { font-family: var(--pd-font-mono); font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--pd-ink-3); }
.scard .v { font: var(--pd-metric); letter-spacing: -0.03em; color: var(--pd-ink); margin-top: 6px; }
.scard .s { font-size: 12px; color: var(--pd-ink-2); margin-top: 3px; }
.scard .s.up { color: var(--pd-live-ink-2); }

.panel {
  background: var(--pd-card); border: 1px solid var(--pd-line);
  border-radius: var(--pd-r-card); box-shadow: var(--pd-shadow-card);
  overflow: hidden; margin-bottom: 16px;
}
.phd {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 16px 20px; border-bottom: 1px solid var(--pd-line);
}
.phd .t { font-family: var(--pd-font-mono); font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--pd-ink-3); }
.phd .c { font-family: var(--pd-font-mono); font-size: 11px; color: var(--pd-ink-3); }
.two { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; margin-bottom: 16px; }
.chartcard { padding: 20px; }
.chartcard .cap {
  font-family: var(--pd-font-mono); font-size: 9.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--pd-ink-3); text-align: center; margin-top: 12px;
}
/* period switch — neutral when selected, per the accent rule */
.ptoggle { display: inline-flex; gap: 8px; flex-wrap: wrap; }
.ptoggle a {
  display: inline-flex; align-items: center; height: 34px; padding: 0 14px;
  border-radius: var(--pd-r-chip); background: var(--pd-card);
  border: 1px solid rgba(20, 22, 34, 0.1); font-size: 13px; color: var(--pd-ink-2);
}
.ptoggle a:hover { text-decoration: none; border-color: var(--pd-brand-600); color: var(--pd-brand-700); }
.ptoggle a.on { background: var(--pd-ink); border-color: transparent; color: #FFFFFF; }
.ptoggle a.on:hover { color: #FFFFFF; }

/* filter chips row */
.pd-chiprow { display: flex; align-items: center; gap: 9px; margin-top: 26px; flex-wrap: wrap; }
a.pd-chip:hover { text-decoration: none; border-color: var(--pd-brand-600); color: var(--pd-brand-700); }
a.pd-chip--on:hover { color: #FFFFFF; }
select.pd-chip { padding: 0 10px; appearance: none; }

/* ---------- form response line -------------------------------------------
   JS writes into .out and toggles .ok / .bad on it. Design never saw these
   three names; they are a contract with the existing JS, so they live here. */
.out { margin-top: 10px; font-size: 13px; line-height: 1.5; min-height: 1.2em; color: var(--pd-ink-2); }
.out.ok  { color: var(--pd-live-ink); }
.out.bad { color: var(--pd-danger-ink); }

/* ==========================================================================
   AUTH SHELL — server-rendered, so the layout lives here rather than in a
   component file. Two shapes only: a split for sign-in and a centred card for
   everything else (Panodock Auth Onboarding.dc.html).
   ========================================================================== */

.pd-auth { min-height: 100vh; }
/* sign-in: form left, testimonial right. Collapses to the card shape early —
   the aside is decoration and must never push the form below the fold. */
.pd-auth--split { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); }
.pd-auth-col { display: flex; align-items: center; justify-content: center; padding: 48px 32px; }
.pd-auth-col > * { width: 100%; max-width: 392px; }
.pd-auth-aside {
  position: relative; overflow: hidden; background: var(--pd-dark);
  display: flex; align-items: center; justify-content: center; padding: 48px 40px;
}
.pd-auth-aside::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(90% 70% at 60% 20%, rgba(37,99,235,0.22), transparent 62%);
}
.pd-auth-aside > * { position: relative; max-width: 400px; }
.pd-auth-quote {
  margin: 34px 0 0; font: 600 22px/1.35 var(--pd-font-display);
  letter-spacing: -0.02em; color: #FFFFFF;
}
@media (max-width: 900px) { .pd-auth--split { grid-template-columns: 1fr; } .pd-auth-aside { display: none; } }

/* centred card: signup 436, forgot/reset/status 400, onboarding 480 */
.pd-auth--card {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 48px 24px; gap: 18px;
}
.pd-sheet {
  width: 100%; max-width: 400px; background: var(--pd-card);
  border: 1px solid var(--pd-line); border-radius: var(--pd-r-modal);
  padding: 30px; box-shadow: var(--pd-shadow-card);
}
.pd-sheet--wide { max-width: 436px; padding: 32px; }
.pd-sheet--onb  { max-width: 480px; padding: 32px; }

/* badge icon on top of a status/confirmation card */
.pd-badge-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 999px;
  background: var(--pd-brand-tint); color: var(--pd-brand-700);
}
.pd-badge-icon--warn    { background: var(--pd-warn-bg); color: var(--pd-warn-ink); }
.pd-badge-icon--neutral { background: var(--pd-sunken); color: var(--pd-ink-2); }
.pd-badge-icon--ok      { background: rgba(16,220,140,0.12); color: var(--pd-live-ink); }

/* "OR EMAIL" rule */
.pd-divider { display: flex; align-items: center; gap: 12px; margin: 20px 0; }
.pd-divider::before, .pd-divider::after { content: ""; flex: 1; height: 1px; background: rgba(20,22,34,0.1); }
.pd-divider > span {
  font-family: var(--pd-font-mono); font-size: 10px;
  letter-spacing: 0.14em; color: var(--pd-ink-2);
}

/* inline field error / hint with a leading glyph */
.pd-msg { display: flex; align-items: center; gap: 7px; margin: 9px 0 0; font-size: 12.5px; color: var(--pd-ink-2); }
.pd-msg--bad  { color: var(--pd-danger-ink); }
.pd-msg--ok   { color: var(--pd-live-ink); }
.pd-msg--warn { color: var(--pd-warn-ink); }

/* password field with a reveal button */
.pd-reveal { position: relative; display: flex; align-items: center; }
.pd-reveal .pd-field { padding-right: 44px; }
.pd-reveal > button {
  position: absolute; right: 6px; width: 32px; height: 32px; border-radius: 8px;
  background: none; border: 0; color: var(--pd-ink-2); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.pd-reveal > button:hover { background: var(--pd-page); color: var(--pd-ink); }

/* password strength meter */
.pd-strength { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.pd-strength > span:first-child { flex: 1 1 auto; display: flex; gap: 4px; }
.pd-strength i { flex: 1; height: 4px; border-radius: 999px; background: var(--pd-sunken); }
.pd-strength-label {
  font-family: var(--pd-font-mono); font-size: 10.5px;
  letter-spacing: 0.1em; flex: 0 0 auto; color: var(--pd-ink-2);
}

/* subdomain: input welded to a fixed .panodock.io suffix */
.pd-sub { display: flex; align-items: stretch; }
.pd-sub .pd-field {
  flex: 1 1 auto; min-width: 0; border-radius: var(--pd-r-field) 0 0 var(--pd-r-field);
  border-right: 0; font-family: var(--pd-font-mono);
}
.pd-sub-suffix {
  display: inline-flex; align-items: center; padding: 0 13px; flex: 0 0 auto;
  border-radius: 0 var(--pd-r-field) var(--pd-r-field) 0;
  background: var(--pd-sunken); border: 1px solid var(--pd-line-strong); border-left: 0;
  font-family: var(--pd-font-mono); font-size: 13.5px; color: var(--pd-ink-2);
}
/* derived-address confirmation strip above the manual field */
.pd-sub-preview {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; margin-top: 12px; padding: 11px 13px;
  border-radius: var(--pd-r-field); background: var(--pd-page);
}
.pd-sub-preview code {
  font-family: var(--pd-font-mono); font-size: 13px; color: var(--pd-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pd-linkbtn {
  background: none; border: 0; padding: 0; cursor: pointer; flex: 0 0 auto;
  font-family: var(--pd-font-body); font-size: 12.5px; color: var(--pd-brand-700);
}
.pd-linkbtn:hover { text-decoration: underline; }

/* two-step progress rail */
.pd-steps { display: flex; align-items: center; gap: 8px; }
.pd-steps i { flex: 1; height: 4px; border-radius: 999px; background: var(--pd-sunken); }
.pd-steps i.on { background: var(--pd-brand-600); }
.pd-steps > span {
  font-family: var(--pd-font-mono); font-size: 10px;
  letter-spacing: 0.1em; color: var(--pd-ink-3); flex: 0 0 auto;
}

/* Turnstile keeps its 300x65 so the button does not jump when it loads */
.pd-turnstile { width: 300px; max-width: 100%; min-height: 65px; margin: 18px auto 0; }

/* button spinner (submitting state) */
@keyframes pd-spin { to { transform: rotate(360deg); } }
.pd-spin {
  width: 16px; height: 16px; border-radius: 999px;
  border: 2px solid rgba(255,255,255,0.35); border-top-color: #FFFFFF;
  animation: pd-spin .9s linear infinite;
}
.pd-spin--ink { border-color: var(--pd-sunken); border-top-color: var(--pd-brand-600); width: 14px; height: 14px; }

/* the slow camera rotation on the auth cards. The node pulse in the mockup
   reaches inside the glyph, which an external <use> cannot do — rotation
   alone carries it. */
.pd-orb { transform-origin: 50% 50%; animation: pd-spin 11s linear infinite; overflow: visible; }
.pd-orb--fast { animation-duration: 9s; }
