/* ========================
   Tendril Terminal — Design System
   Aurelia Intelligence Corporation
   ======================== */

@import url('https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;1,400;1,600&family=Instrument+Serif:ital@0;1&family=Lexend:wght@300;400;500;600;700&display=swap');

/* ========================
   CSS Variables / Theming
   ======================== */
:root {
  /* Backgrounds */
  --bg-void: #0c1214;
  --bg-card: #131e1f;
  --bg-card-gradient: linear-gradient(165deg, #151f21, #0f1819);
  --bg-inset: #0e1816;
  --bg-elevated: #172322;

  /* Teal — Primary Accent */
  --teal-bright: #5aaa82;
  --teal-mid: #4a8a72;
  --teal-muted: #3a6a52;
  --teal-dim: #2a4a38;
  --teal-ghost: #1a2e24;

  /* Glow colors */
  --glow-teal: rgba(74, 138, 114, 0.12);
  --glow-teal-strong: rgba(90, 170, 130, 0.2);
  --glow-gold: rgba(138, 122, 82, 0.08);

  /* Type scale. Every font-size in the sheet is one of these, so a change to a
     step lands everywhere that step is used rather than in one rule.

       fine       footer, badges, eyebrows, field labels
       meta       small buttons, tile blurbs, fine print
       label      nav, the status indicator, form messages, flash
       control    buttons, inputs, table cells
       lead       the wordmark, tile names, large buttons
       body       prose, the reading size
       title      card and section headings, the welcome lede
       display*   the three page-opening numerals and greetings

     The three display steps have their own smaller values inside the 768px
     breakpoint, which is the one place a literal is still the right answer. */
  --size-fine: 12px;
  --size-meta: 13px;
  --size-label: 14px;
  --size-control: 15px;
  --size-lead: 16px;
  --size-body: 19px;
  --size-title: 21px;
  --size-display: 48px;
  --size-display-lg: 70px;
  --size-display-xl: 80px;

  /* Body copy and anything that reads as content. */
  --text-body: #d0f7e1;
  /* --text-white keeps its name for continuity — a great many rules already
     reference it, and it is no longer white. Prefer --text-body in
     anything written from here on. */
  --text-white: var(--text-body);

  /* Titles and the brand: the wordmark, page and card headings, nav, and an
     app name on a launch tile. Everything that is not a title is body mint. */
  --text-title: var(--teal-bright);

  /* Button labels, on every variant. The same mint the body copy takes, kept
     as its own token so the two can part ways again without a sweep. */
  --text-button: #d0f7e1;

  /* The pale green the wordmark and the online status label glow with. Paired
     with the tendrilHaze animation; not a flat text colour on its own. */
  --text-haze: #c8f5dd;

  /* Header connection indicator. Signed out borrows the gold the footer sets
     the Aurelia mark in, so the two warm things on the page agree. */
  --dot-online: #bcfddd;
  --dot-offline: var(--gold-bright);
  --text-offline: var(--gold-bright);

  /* Neutrals */
  --text-primary: var(--text-body);
  /* Unused since the content headings took the mint. Kept for now rather than
     deleted, in case a middle step between mint and --text-muted is wanted. */
  --text-secondary: #a8c4b4;
  --text-muted: #7a9a8a;
  --text-dim: #5a7a6a;
  --text-ghost: #4a6a5a;
  --text-buried: #3a5a4a;
  --text-almost-gone: #2a3a32;

  /* Borders */
  --border-default: #1e2e28;
  --border-hover: #2a4a3a;
  --border-active: #3a6a52;
  --border-faint: #1a2822;
  --border-inset: #1a2420;

  /* Status Colors */
  --status-confirmed-bg: #1a2e24;
  --status-confirmed-text: #5aaa82;
  --status-confirmed-border: #2a4a36;
  --status-pending-bg: #2a2218;
  --status-pending-text: #c49a5a;
  --status-pending-border: #4a3a22;
  /* Errors and destructive actions took a coral (#c47a4a) until now. They take
     Aurelia's gold instead, so the product carries one warm colour rather than
     two. */
  --status-hot: var(--gold-bright);

  /* Gold Trace — Aurelia's Ghost */
  --gold-trace: #8a7a52;
  /* The brighter gold the footer brand is set in. Aurelia's own identity
     colour, and now the only warm colour in the product: the wordmark, the
     signed-out indicator, and every error and destructive action. */
  --gold-bright: #f9d891;

  /* The footer copyright line, quieter than the links above it. */
  --text-copyright: #6a7a6a;

  /* Error */
  --color-error: var(--gold-bright);

  /* Layout */
  --max-width: 1200px;
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 2rem;
  --spacing-xl: 4rem;
  --radius: 12px;
  /* Every button edge. One value, so the whole set thickens or thins together. */
  --border-button: 2px;

  /* Fonts */
  /* --font-mono keeps its name for continuity — it is the body face used
     everywhere, and is no longer monospaced. Regular (400) is the base weight. */
  --font-mono: 'Crimson Text', 'Instrument Serif', Georgia, serif;
  --font-serif: 'Instrument Serif', serif;
  /* The footer's layout font. Every element down there sets Crimson Text on
     itself, so this only governs anything added to the footer later. */
  --font-sans: 'Lexend', system-ui, sans-serif;
}

/* ========================
   Reset & Base
   ======================== */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scrollbar-color: var(--text-almost-gone) var(--bg-void);
}

body {
  font-family: var(--font-mono);
  background-color: var(--bg-void);
  color: var(--text-primary);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-size: var(--size-body);
  /* Crimson Text Regular. */
  font-weight: 400;
  position: relative;
  background-image:
    radial-gradient(ellipse 80% 60% at 50% 0%, rgba(20, 40, 35, 0.6) 0%, transparent 70%),
    radial-gradient(ellipse 60% 50% at 80% 100%, rgba(14, 30, 25, 0.4) 0%, transparent 60%);
}

/* Noise Texture Overlay */
body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 9999;
  opacity: 0.018;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 256px 256px;
}

a {
  color: var(--text-white);
  text-decoration: none;
  transition: color 0.3s ease;
}

a:hover {
  color: var(--text-white);
  /* The green used to be the only thing marking a link. With links now the
     same mint as the copy around them, the underline carries that job. */
  text-decoration: underline;
}

/* ========================
   Atmospheric Background Glows
   ======================== */
.atmosphere-glow {
  opacity: 0;
  will-change: opacity;
}

/* ========================
   Layout
   ======================== */
.container {
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: var(--spacing-lg);
  flex: 1;
  position: relative;
  z-index: 1;
}

/* ========================
   Header
   ======================== */
.site-header {
  /* Frosted glass: translucent over the blur, and the same tint all the way
     to the bottom edge so scrolled content reads as blurred, not exposed. */
  background: rgba(12, 18, 20, 0.55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: none;
  padding: var(--spacing-md) var(--spacing-lg);
  position: sticky;
  top: 0;
  z-index: 100;
}

/* Header hairline */
.site-header::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 5%;
  right: 5%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(74, 138, 114, 0.15), rgba(74, 138, 114, 0.25), rgba(74, 138, 114, 0.15), transparent);
}

/* Two things sit in the bar: the wordmark at one end and everything else at
   the other. Nothing is centred any more, so the three-column grid that used
   to hold the indicator in the middle is gone and the ends are simply pushed
   apart. */
.nav-container {
  max-width: var(--max-width);
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--spacing-md);
}

/* The right-hand end of the bar. Signed in it carries the account nav with the
   indicator after it; signed out the indicator is all there is. */
.nav-right {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
}

.logo {
  font-family: var(--font-mono);
  font-size: var(--size-lead);
  font-weight: 600;
  color: var(--text-haze);
  letter-spacing: 1.5px;
  transition: color 0.3s ease;
  animation: tendrilHaze 4s ease-in-out infinite;
}

.logo:hover {
  text-decoration: none;
  color: var(--text-haze);
}

/* The green bloom the wordmark, the online label and the hero's call to action
   all breathe with. Four stacked shadows so the glow has a core and a falloff
   rather than one flat halo. */
@keyframes tendrilHaze {
  0%, 100% {
    text-shadow:
      0 0 4px rgba(200, 245, 221, 0.85),
      0 0 10px rgba(120, 220, 160, 0.6),
      0 0 20px rgba(90, 170, 130, 0.45),
      0 0 36px rgba(74, 138, 114, 0.3);
  }
  50% {
    text-shadow:
      0 0 6px rgba(200, 245, 221, 1),
      0 0 16px rgba(120, 220, 160, 0.85),
      0 0 30px rgba(90, 170, 130, 0.7),
      0 0 52px rgba(74, 138, 114, 0.5);
  }
}

/* ========================
   Header connection status
   Sits between the wordmark and the account nav in both states. Online is a
   signed-in account, Offline is a signed-out one; neither has to do with the
   network.
   ======================== */
.conn-status {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-sm);
}

.conn-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--dot-online);
  animation: tendrilDotPulse 2.4s ease-in-out infinite;
}

.conn-label {
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.5px;
  color: var(--text-haze);
  animation: tendrilHaze 4s ease-in-out infinite;
}

/* Offline is a warning, not a mood: the dot holds steady and the glow stops,
   so a dropped connection reads as different in kind rather than in colour. */
.conn-status.is-offline .conn-dot {
  background: var(--dot-offline);
  animation: goldDotPulse 2.4s ease-in-out infinite;
}

.conn-status.is-offline .conn-label {
  color: var(--text-offline);
  animation: goldHaze 4s ease-in-out infinite;
}

/* The gold twin of tendrilHaze and tendrilDotPulse. Signed out breathes the
   same way signed in does, so the indicator always reads as live and only the
   colour says which state it is in. */
@keyframes goldHaze {
  0%, 100% {
    text-shadow:
      0 0 4px rgba(255, 244, 214, 0.85),
      0 0 10px rgba(249, 216, 145, 0.6),
      0 0 20px rgba(220, 185, 110, 0.45),
      0 0 36px rgba(180, 145, 80, 0.3);
  }
  50% {
    text-shadow:
      0 0 6px rgba(255, 244, 214, 1),
      0 0 16px rgba(249, 216, 145, 0.85),
      0 0 30px rgba(220, 185, 110, 0.7),
      0 0 52px rgba(180, 145, 80, 0.5);
  }
}

@keyframes goldDotPulse {
  0%, 100% {
    box-shadow:
      0 0 4px rgba(249, 216, 145, 0.9),
      0 0 10px rgba(220, 185, 110, 0.7),
      0 0 18px rgba(249, 216, 145, 0.5);
  }
  50% {
    box-shadow:
      0 0 6px rgba(255, 244, 214, 1),
      0 0 16px rgba(249, 216, 145, 0.9),
      0 0 30px rgba(220, 185, 110, 0.7);
  }
}

@keyframes tendrilDotPulse {
  0%, 100% {
    box-shadow:
      0 0 4px rgba(90, 170, 130, 0.9),
      0 0 10px rgba(120, 220, 160, 0.7),
      0 0 18px rgba(90, 170, 130, 0.5);
  }
  50% {
    box-shadow:
      0 0 6px rgba(200, 245, 221, 1),
      0 0 16px rgba(120, 220, 160, 0.9),
      0 0 30px rgba(90, 170, 130, 0.7);
  }
}

.nav-links {
  display: flex;
  gap: var(--spacing-md);
  list-style: none;
  align-items: center;
}

.nav-links a {
  color: var(--text-title);
  font-size: var(--size-label);
  letter-spacing: 0.5px;
  transition: color 0.3s ease, text-shadow 0.3s ease;
}

.nav-links a:hover {
  color: var(--text-title);
  text-shadow: 0 0 12px rgba(90, 170, 130, 0.2);
}

.nav-links li {
  display: flex;
  align-items: center;
}

.logout-form {
  display: flex;
  align-items: center;
}

/* A button among anchors: the padding and line-height are zeroed so it sits on
   the same line as the links either side of it rather than riding a taller box. */
.btn-link {
  background: none;
  border: none;
  padding: 0;
  line-height: 1;
  color: var(--text-title);
  cursor: pointer;
  font-size: var(--size-label);
  font-family: var(--font-mono);
  letter-spacing: 0.5px;
  transition: color 0.3s ease;
}

.btn-link:hover {
  color: var(--text-title);
  text-decoration: none;
}

/* ========================
   Footer
   ======================== */
.site-footer {
  background-color: transparent;
  border-top: none;
  padding: var(--spacing-lg);
  margin-top: auto;
  position: relative;
  z-index: 1;
  font-family: var(--font-sans);
  /* Everything down here is 12px to 16px, deliberately under the body reading
     size. The footer is chrome, not copy. */
  font-size: var(--size-fine);
  line-height: 1.6;
}

.footer-container {
  max-width: var(--max-width);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 10px;
}

.footer-container p {
  font-family: var(--font-mono);
  color: var(--text-copyright);
  font-size: var(--size-fine);
}

.footer-links {
  display: flex;
  gap: 20px;
  list-style: none;
}

.footer-links a {
  font-family: var(--font-mono);
  color: var(--text-body);
  font-size: var(--size-fine);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: capitalize;
  transition: color 0.3s ease;
}

.footer-links a:hover {
  color: var(--text-haze);
}

/* Aurelia's own identity, borrowed: their italic and their gold, and nothing
   else of theirs. */
.aurelia-mark {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-style: italic;
  font-size: var(--size-lead);
  color: var(--gold-bright);
  text-decoration: none;
  transition: filter 0.6s ease;
}

.aurelia-mark:hover {
  filter: drop-shadow(0 0 12px rgba(249, 216, 145, 0.35));
}

/* Stacked above the name rather than beside it. 80px is the middle of the band
   a centred company mark usually sits in down here, roughly 72px to 96px; the
   source art is 4847px square, so there is no sharpness cost to the size. */
.aurelia-logo {
  height: 80px;
  width: auto;
  display: block;
}

/* ========================
   Buttons
   One shape, one border weight, one type size. Variants set colour and nothing
   else, so a change to the pill lands on every button at once.
   ======================== */
.btn {
  color: var(--text-button);
  display: inline-block;
  padding: var(--spacing-sm) var(--spacing-md);
  border-radius: 999px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  /* Transparent rather than none, so a button with no edge of its own still
     stands the same height as one that has a visible edge. */
  border: var(--border-button) solid transparent;
  font-size: var(--size-control);
  font-family: var(--font-mono);
  letter-spacing: 0.5px;
  transition: all 0.35s ease;
  position: relative;
}

.btn:hover {
  text-decoration: none;
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

/* Glass rather than a filled slab: a teal wash the layered background shows
   through, with a bright inner top edge so the pill still reads as raised. */
.btn-primary {
  background: rgba(90, 170, 130, 0.12);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--text-button);
  border-color: rgba(208, 247, 225, 0.25);
  box-shadow:
    0 4px 24px rgba(0, 0, 0, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.15);
}

.btn-primary:hover {
  background: rgba(90, 170, 130, 0.2);
  border-color: rgba(208, 247, 225, 0.45);
  box-shadow:
    0 6px 28px rgba(0, 0, 0, 0.3),
    0 0 30px rgba(74, 138, 114, 0.15),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

.btn-secondary {
  background: transparent;
  color: var(--text-button);
  border-color: var(--border-hover);
}

.btn-secondary:hover {
  background: #1a2a22;
  color: var(--text-button);
  border-color: var(--teal-muted);
  box-shadow: 0 0 20px rgba(74, 138, 114, 0.08);
}

.btn-small {
  padding: 0.25rem 0.75rem;
  font-size: var(--size-meta);
}

.btn-outline {
  background: transparent;
  border-color: var(--border-hover);
  color: var(--text-button);
}

.btn-outline:hover {
  background: rgba(26, 46, 36, 0.6);
  border-color: var(--teal-muted);
  box-shadow: 0 0 20px rgba(74, 138, 114, 0.1);
}

/* Destructive actions. Outlined rather than filled — it should read as a real
   button but never as the obvious thing to press. */
.btn-danger {
  background: transparent;
  /* Gold label to match the gold edge, the way the mint buttons carry mint. */
  color: var(--color-error);
  border-color: rgba(249, 216, 145, 0.35);
}

.btn-danger:hover {
  background: rgba(249, 216, 145, 0.1);
  border-color: var(--color-error);
  box-shadow: 0 0 20px rgba(249, 216, 145, 0.12);
}

/* ========================
   OAuth Buttons
   ======================== */
.oauth-buttons {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-lg);
}

/* Always carries .btn as well, so this only adds what makes it different: the
   full width of the sign-in card, and a filled inset rather than glass. */
.btn-oauth {
  display: block;
  width: 100%;
  padding: var(--spacing-md);
  background-color: var(--bg-inset);
  border-color: var(--border-default);
}

.btn-oauth:hover {
  border-color: var(--border-hover);
  background-color: var(--teal-ghost);
  box-shadow: 0 0 20px rgba(74, 138, 114, 0.06);
}

/* ========================
   Forms
   ======================== */
.form-group {
  margin-bottom: var(--spacing-md);
}

.form-group label {
  display: block;
  margin-bottom: var(--spacing-sm);
  font-weight: 400;
  font-size: var(--size-fine);
  letter-spacing: 1.5px;
  color: var(--text-ghost);
  transition: color 0.3s ease;
}

.form-group:focus-within label {
  color: var(--text-white);
}

.form-group input {
  width: 100%;
  padding: 10px var(--spacing-md);
  /* Resting state is seamless with the fill; :focus below still draws a real
     border, which is the one place the outline has to be visible. */
  border: 1px solid var(--bg-inset);
  border-radius: 8px;
  font-size: var(--size-control);
  font-family: var(--font-mono);
  background: var(--bg-inset);
  color: var(--text-primary);
  transition: all 0.4s ease;
}

.form-group input::placeholder {
  color: var(--text-buried);
}

.form-group input:focus {
  outline: none;
  border-color: var(--border-active);
  box-shadow:
    0 0 0 3px rgba(74, 138, 114, 0.1),
    0 0 20px rgba(74, 138, 114, 0.06);
  background: rgba(14, 24, 22, 0.8);
}

.input-error {
  border-color: var(--status-hot) !important;
  box-shadow:
    0 0 0 3px rgba(249, 216, 145, 0.1),
    0 0 16px rgba(249, 216, 145, 0.05) !important;
}

.form-error {
  font-family: var(--font-mono);
  font-size: var(--size-label);
  color: var(--color-error);
  background: rgba(249, 216, 145, 0.08);
  border: 1px solid rgba(249, 216, 145, 0.25);
  border-radius: 8px;
  padding: var(--spacing-sm) var(--spacing-md);
  margin-bottom: var(--spacing-md);
  line-height: 1.6;
}

.form-notice {
  font-family: var(--font-mono);
  font-size: var(--size-label);
  color: var(--text-white);
  background: rgba(74, 138, 114, 0.08);
  border: 1px solid rgba(74, 138, 114, 0.25);
  border-radius: 8px;
  padding: var(--spacing-sm) var(--spacing-md);
  margin-bottom: var(--spacing-md);
  line-height: 1.6;
}

.transactions {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: var(--size-control);
}
.transactions th,
.transactions td {
  text-align: left;
  padding: var(--spacing-sm) var(--spacing-md);
  border-bottom: 1px solid rgba(74, 138, 114, 0.15);
}
/* The header row reads as the same line of text as the row under it: same
   size, same mint. Weight alone marks it as the header. */
.transactions th {
  font-weight: 600;
  color: var(--text-body);
}
.transactions .tx-id {
  font-size: var(--size-meta);
  color: var(--text-buried);
  word-break: break-all;
}

/* Wide tables scroll sideways inside their card instead of pushing past
   the screen edge. The diagnostics table keeps every cell on one line so the
   columns stay readable while it scrolls. */
.table-scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.diag-table th,
.diag-table td {
  white-space: nowrap;
}
.diag-table td:nth-child(3) {
  white-space: normal;
  word-break: break-all;
  min-width: 12rem;
}
.diag-summary {
  color: var(--text-body);
  margin-bottom: var(--spacing-md);
}

/* ========================
   Danger Zone
   Irreversible actions. The panel is folded away behind its own button, so it
   no longer draws a rule across the top to wall itself off.
   ======================== */

.danger-zone h2 {
  font-family: var(--font-mono);
  font-size: var(--size-title);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--color-error);
  margin-bottom: var(--spacing-sm);
}

/* Narrowed past .form-error and .form-notice: a bare descendant selector
   outranks those classes and would repaint the delete error as body copy. */
.danger-zone p:not(.form-error):not(.form-notice) {
  font-size: var(--size-body);
  color: var(--text-white);
  line-height: 1.7;
  margin-bottom: var(--spacing-md);
}

/* The delete panel, folded behind its own button. <details> rather than a
   script, so the fold still works with JavaScript off. It sits at the foot of
   the Sign-in card, whose own padding clears it, so it carries no margin. */
.danger-reveal {
  margin-bottom: 0;
}

/* Against the right-hand edge of its card, like every other card button. A
   <summary> is not a button, so as a block it needs telling to keep its own
   width before the auto margin can push it across. */
.danger-reveal-trigger {
  display: block;
  width: fit-content;
  margin-left: auto;
  list-style: none;
}

.danger-reveal-trigger::-webkit-details-marker {
  display: none;
}

/* Once the panel is open the trigger has done its job, so it gets out of the
   way rather than sitting above its own contents. */
.danger-reveal[open] .danger-reveal-trigger {
  display: none;
}

/* The card around the fold takes the page's entrance with the rest. The panel
   inside it is hidden until opened, so it sets its own visibility and animates
   on open instead. */
.danger-reveal .danger-panel {
  opacity: 1;
  animation: none;
}

.danger-reveal[open] .danger-panel {
  animation: fadeSlideUp 0.4s ease-out;
}

.danger-echo {
  color: var(--text-white);
  word-break: break-all;
}

.diag-delete {
  display: inline;
}

.divider {
  display: flex;
  align-items: center;
  margin: var(--spacing-lg) 0;
  color: var(--text-buried);
}

.divider::before,
.divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, #4a8a7218, #4a8a7228, #4a8a7218, transparent);
}

.divider span {
  padding: 0 var(--spacing-md);
  font-size: var(--size-fine);
  letter-spacing: 1.5px;
}

/* ========================
   Auth Form
   ======================== */
/* Sign-in, privacy, terms and support all use this card, and their copy is
   plain unclassed paragraphs, so the reading size is set here for them to
   inherit. */
.auth-form {
  max-width: 420px;
  font-size: var(--size-body);
  line-height: 1.7;
  margin: var(--spacing-xl) auto;
  padding: var(--spacing-lg) calc(var(--spacing-lg) + 0.5rem);
  background: var(--bg-card-gradient);
  border-radius: var(--radius);
  border: 1px solid #151f21;
  position: relative;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
  transition: box-shadow 0.6s ease;
}

.auth-form:hover {
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
}

/* Privacy and Terms run to several paragraphs, and the global reset zeroes the
   margins they would otherwise separate on. */
.auth-form p {
  margin-bottom: var(--spacing-md);
}

.auth-form p:last-child {
  margin-bottom: 0;
}

.auth-form h1 {
  margin-bottom: var(--spacing-lg);
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--size-body);
  font-weight: 600;
  color: var(--text-title);
  letter-spacing: 1.5px;
}

.auth-form .btn-primary {
  width: 100%;
  padding: 12px var(--spacing-md);
}

/* Sign in with Google — the only action on the login page, so it carries it */
.auth-form .btn-oauth {
  display: block;
  width: 100%;
  padding: 12px var(--spacing-md);
  background: var(--bg-elevated);
  color: var(--text-button);
  border: 1px solid var(--border-hover);
}

.auth-form .btn-oauth:hover {
  color: var(--text-button);
  border-color: var(--teal-muted);
  box-shadow: 0 0 20px rgba(74, 138, 114, 0.08);
}

.auth-footer {
  margin-top: var(--spacing-lg);
  text-align: center;
  color: var(--text-white);
  font-size: var(--size-lead);
}

.auth-footer a {
  color: var(--text-white);
}

/* ========================
   Hero Section
   ======================== */
.hero {
  text-align: center;
  padding: 8rem 0 7.5rem;
  position: relative;
}

.hero h1 {
  font-family: var(--font-serif);
  font-size: var(--size-display-lg);
  font-weight: 400;
  font-style: italic;
  color: var(--text-title);
  margin-bottom: var(--spacing-lg);
  line-height: 1.15;
  text-shadow:
    0 0 40px rgba(90, 170, 130, 0.15),
    0 0 80px rgba(74, 138, 114, 0.06);
  opacity: 0;
  animation: heroReveal 1s ease-out 0.4s forwards;
}

@keyframes heroReveal {
  from {
    opacity: 0;
    transform: translateY(16px);
    text-shadow: 0 0 40px rgba(90, 170, 130, 0), 0 0 80px rgba(74, 138, 114, 0);
  }
  to {
    opacity: 1;
    transform: translateY(0);
    text-shadow: 0 0 40px rgba(90, 170, 130, 0.15), 0 0 80px rgba(74, 138, 114, 0.06);
  }
}

.hero p {
  font-size: var(--size-body);
  color: var(--text-body);
  margin-bottom: var(--spacing-lg);
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
  line-height: 1.9;
  opacity: 0;
  animation: fadeSlideUp 0.8s ease-out 0.7s forwards;
}

/* The one button that breathes. The haze is held back until the entrance has
   finished so the two animations do not fight over the first second. */
.hero .btn {
  opacity: 0;
  animation:
    fadeSlideUp 0.8s ease-out 0.9s forwards,
    tendrilHaze 4s ease-in-out 1.7s infinite;
}

.hero-actions {
  display: flex;
  gap: var(--spacing-md);
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
}

/* ========================
   Terminal Lines
   ======================== */
.terminal-line {
  font-family: var(--font-mono);
  font-size: var(--size-body);
  color: var(--text-white);
  margin: var(--spacing-sm) 0;
}

.terminal-line .prompt {
  color: var(--text-white);
  margin-right: 0.5rem;
  user-select: none;
}

.btn-large {
  padding: var(--spacing-md) var(--spacing-lg);
  font-size: var(--size-lead);
}

/* ========================
   Section Markers
   ======================== */
.section-marker {
  margin-bottom: var(--spacing-md);
}

.section-marker h2 {
  font-size: var(--size-title);
  font-weight: 600;
  color: var(--text-title);
  font-family: var(--font-mono);
  margin: 0;
}

/* ========================
   Dashboard
   ======================== */
.dashboard {
  position: relative;
}

.dashboard-greeting {
  font-family: var(--font-serif);
  font-size: var(--size-display);
  font-weight: 400;
  font-style: italic;
  color: var(--text-title);
  margin-bottom: calc(var(--spacing-lg) + 0.5rem);
  line-height: 1.2;
  text-shadow:
    0 0 30px rgba(90, 170, 130, 0.12),
    0 0 60px rgba(74, 138, 114, 0.04);
}

.dashboard-greeting span {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--size-label);
  font-style: normal;
  display: block;
  margin-bottom: 8px;
  letter-spacing: 2px;
  text-shadow: none;
}

/* ========================
   App launch tiles
   ======================== */
/* auto-fit with a ceiling rather than auto-fill with 1fr: empty tracks collapse
   and the tiles that exist stay a sane size instead of stretching to fill the
   card. Centred, so a single connected app lands in the middle of the row
   rather than tucked against the left edge. */
.launch-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 240px));
  justify-content: center;
  gap: var(--spacing-md);
}

/* Square by design — aspect-ratio keeps the tiles square at every width. */
.launch-tile {
  aspect-ratio: 1 / 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--spacing-sm);
  padding: var(--spacing-md);
  text-align: center;
  border: 1px solid var(--bg-inset);
  border-radius: var(--radius);
  background: var(--bg-inset);
  color: var(--text-primary);
  font-family: var(--font-mono);
  transition: all 0.35s ease;
}

.launch-tile:hover {
  text-decoration: none;
  transform: translateY(-2px);
  border-color: var(--teal-muted);
  background: var(--teal-ghost);
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.35),
    0 0 30px rgba(74, 138, 114, 0.12);
}

/* Unpaid: same footprint, visibly inert — no hover lift, no pointer. */
.launch-tile-locked,
.launch-tile-locked:hover {
  opacity: 0.45;
  transform: none;
  cursor: default;
  border-color: var(--bg-inset);
  background: var(--bg-inset);
  box-shadow: none;
}

/* Square artwork, sized off the tile so it stays proportional as the grid
   reflows. Decorative — the app name right below it carries the meaning. */
.launch-tile-icon {
  width: clamp(48px, 38%, 96px);
  height: auto;
  margin: 0 auto;
  display: block;
  transition: transform 0.35s ease;
}

.launch-tile:not(.launch-tile-locked):hover .launch-tile-icon {
  transform: scale(1.05);
}

.launch-tile-locked .launch-tile-icon {
  filter: grayscale(1);
}

.launch-tile-name {
  font-size: var(--size-lead);
  font-weight: 600;
  color: var(--text-title);
  letter-spacing: 0.5px;
}

.launch-tile-blurb {
  font-size: var(--size-meta);
  color: var(--text-white);
  line-height: 1.5;
}

.launch-tile-action {
  font-size: var(--size-meta);
  color: var(--text-dim);
  letter-spacing: 0.5px;
}

.launch-tile:not(.launch-tile-locked):hover .launch-tile-action {
  color: var(--text-white);
}

/* ========================
   Cards
   ======================== */
.card {
  background: var(--bg-card-gradient);
  border-radius: var(--radius);
  padding: var(--spacing-lg);
  margin-bottom: var(--spacing-md);
  /* Matches the top of the card's own gradient, so the edge reads as the
     surface ending rather than as an outline drawn around it. */
  border: 1px solid #151f21;
  position: relative;
  transition: box-shadow 0.6s ease, transform 0.4s ease;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}

/* Top edge highlight */
/* Bottom hairline */
.card:hover {
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  transform: translateY(-1px);
}

.card h2 {
  /* A step above --size-body: at 16px this read smaller than the .card-lede
     underneath it, which put a heading below its own copy. */
  font-size: var(--size-title);
  font-weight: 600;
  color: var(--text-title);
  margin-bottom: var(--spacing-md);
}

/* A form's button sits against the right-hand edge of its card. Block plus an
   auto left margin rather than text-align on the form, so the labels and inputs
   above it stay where they are. A button keeps its own width as a block. */
.card form > .btn {
  display: block;
  margin-left: auto;
}

.placeholder {
  color: var(--text-dim);
  font-style: italic;
  font-size: var(--size-body);
}

.dashboard-links {
  list-style: none;
}

.dashboard-links li {
  padding: var(--spacing-sm) 0;
  position: relative;
}

.dashboard-links li + li {
  border-top: none;
}

.dashboard-links a {
  color: var(--text-white);
  font-size: var(--size-control);
  transition: color 0.3s ease, padding-left 0.3s ease;
  display: inline-block;
}

.dashboard-links a:hover {
  color: var(--text-white);
  padding-left: 4px;
}

/* ========================
   Status Badges
   ======================== */
.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 12px;
  font-size: var(--size-fine);
  font-weight: 600;
  font-family: var(--font-mono);
  letter-spacing: 0.5px;
}

.badge-confirmed {
  background: var(--status-confirmed-bg);
  color: var(--status-confirmed-text);
  border: 1px solid var(--status-confirmed-border);
  box-shadow: 0 0 8px rgba(90, 170, 130, 0.08);
}

.badge-pending {
  background: var(--status-pending-bg);
  color: var(--status-pending-text);
  border: 1px solid var(--status-pending-border);
  box-shadow: 0 0 8px rgba(196, 154, 90, 0.06);
}

/* ========================
   Error Pages
   ======================== */
.error-page {
  text-align: center;
  padding: var(--spacing-xl) 0;
  padding-top: 8rem;
}

.error-page h1 {
  font-family: var(--font-serif);
  font-size: var(--size-display-xl);
  font-weight: 400;
  font-style: italic;
  color: var(--teal-dim);
  margin-bottom: var(--spacing-md);
  text-shadow: 0 0 40px rgba(42, 74, 56, 0.3);
  opacity: 0;
  animation: heroReveal 1s ease-out 0.3s forwards;
}

.error-page p {
  color: var(--text-white);
  margin-bottom: var(--spacing-lg);
  font-size: var(--size-body);
  line-height: 1.8;
}

.error-details {
  text-align: left;
  margin: var(--spacing-lg) auto;
  max-width: 600px;
  background: var(--bg-inset);
  padding: var(--spacing-md);
  border-radius: var(--radius);
  border: 1px solid var(--border-inset);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
}

.error-details summary {
  color: var(--text-dim);
  cursor: pointer;
  font-size: var(--size-label);
  letter-spacing: 0.5px;
}

.error-details pre {
  overflow-x: auto;
  font-size: var(--size-label);
  color: var(--status-hot);
  margin-top: var(--spacing-sm);
  /* Stack traces are the one place that still needs real fixed-width. */
  font-family: 'Fira Code', 'Courier New', monospace;
}

/* ========================
   Search Bar
   ======================== */
.search-bar {
  position: relative;
  margin-bottom: var(--spacing-lg);
}

.search-bar input {
  width: 100%;
  padding: 10px 16px;
  border: 1px solid var(--border-default);
  border-radius: 20px;
  background: var(--bg-inset);
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--size-control);
  transition: all 0.4s ease;
}

.search-bar input::placeholder {
  color: var(--text-buried);
}

.search-bar input:focus {
  outline: none;
  border-color: var(--border-active);
  box-shadow:
    0 0 0 3px rgba(74, 138, 114, 0.08),
    0 0 24px rgba(74, 138, 114, 0.06);
}

/* ========================
   Animations
   ======================== */
@keyframes fadeSlideUp {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes ambientGlow {
  0%, 100% { opacity: 0.03; }
  50% { opacity: 0.08; }
}

@keyframes breathe {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}

/* Staggered entrance animations */
.animate-in {
  opacity: 0;
  animation: fadeSlideUp 0.6s ease-out forwards;
}

.animate-in:nth-child(1) { animation-delay: 0.15s; }
.animate-in:nth-child(2) { animation-delay: 0.3s; }
.animate-in:nth-child(3) { animation-delay: 0.45s; }
.animate-in:nth-child(4) { animation-delay: 0.6s; }
.animate-in:nth-child(5) { animation-delay: 0.75s; }

/* ========================
   Flash Messages
   ======================== */
.flash {
  padding: var(--spacing-sm) var(--spacing-md);
  border-radius: 8px;
  margin-bottom: var(--spacing-md);
  font-size: var(--size-label);
  border: 1px solid;
}

.flash-success {
  background: var(--status-confirmed-bg);
  color: var(--status-confirmed-text);
  border-color: var(--status-confirmed-border);
  box-shadow: 0 0 16px rgba(90, 170, 130, 0.06);
}

.flash-error {
  background: var(--status-pending-bg);
  color: var(--status-hot);
  border-color: var(--status-pending-border);
}

/* ========================
   Responsive
   ======================== */
@media (max-width: 768px) {
  /* Stays a single row: four short items fit, and stacking them was what put
     the wordmark, the indicator and the nav on three different lines. Wrapping
     is the fallback if a very narrow screen genuinely runs out of room. */
  .nav-container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--spacing-md);
  }

  .footer-container {
    flex-direction: column;
    text-align: center;
  }

  .hero {
    padding-top: 5rem;
  }

  .hero h1 {
  color: var(--text-title);
    font-size: 38px;
  }

  .dashboard-greeting {
  color: var(--text-title);
    font-size: 36px;
  }

  .error-page {
    padding-top: 5rem;
  }

  .error-page h1 {
    font-size: 52px;
  }

  .card:hover {
    transform: none;
  }

  .btn:hover {
    transform: none;
  }
}

/* ========================
   Reduced Motion
   ======================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .animate-in {
    opacity: 1;
  }

  .hero h1,
  .hero p,
  .hero .btn {
    opacity: 1;
  }
}
/* ========================
   Onboarding — one-time hint cards
   Deliberately not a modal: it sits in the flow above the thing it describes,
   so nothing is blocked and dismissing it is a choice rather than a toll.
   ======================== */
.hint-card {
  display: flex;
  align-items: flex-start;
  gap: var(--spacing-lg);
  margin-bottom: var(--spacing-lg);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--bg-inset);
  border: none;
  border-radius: var(--radius);
  box-shadow: 0 0 24px var(--glow-teal);
}

.hint-card.is-dismissing {
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.hint-text {
  flex: 1;
  min-width: 0;
}

.hint-title {
  margin: 0 0 var(--spacing-sm);
  font-family: var(--font-mono);
  font-size: var(--size-meta);
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--text-title);
}

.hint-text p {
  margin: 0;
  color: var(--text-white);
  font-size: var(--size-body);
  line-height: 1.65;
}

.hint-text strong {
  color: var(--text-primary);
  font-weight: 600;
}

.hint-form {
  flex-shrink: 0;
}

/* The dismiss button is a plain .btn .btn-secondary .btn-small now. It used to
   carry its own square, thin-edged shape, which was the one button in the
   product that did not match the rest. */

@media (max-width: 620px) {
  .hint-card {
    flex-direction: column;
    gap: var(--spacing-md);
  }

  /* Stacked under the text, the button still keeps to the right-hand side. */
  .hint-form {
    align-self: flex-end;
  }
}

/* ========================
   Onboarding — the /welcome page
   ======================== */
.welcome {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--spacing-xl) 0;
}

.welcome-head {
  margin-bottom: var(--spacing-xl);
}

.welcome-eyebrow {
  margin: 0 0 var(--spacing-sm);
  font-family: var(--font-mono);
  font-size: var(--size-fine);
  letter-spacing: 0.22em;
  color: var(--text-title);
}

.welcome-head h1 {
  margin: 0 0 var(--spacing-md);
  font-family: var(--font-serif);
  font-size: clamp(2rem, 5vw, 3rem);
  font-weight: 400;
  color: var(--text-primary);
}

.welcome-lede {
  margin: 0;
  color: var(--text-white);
  font-size: var(--size-title);
  line-height: 1.7;
}

.welcome-steps {
  list-style: none;
  margin: 0 0 var(--spacing-xl);
  padding: 0;
}

.welcome-steps li {
  display: flex;
  gap: var(--spacing-lg);
  padding: var(--spacing-lg) 0;
  border-top: 1px solid var(--border-faint);
}

.welcome-step-mark {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: var(--size-meta);
  letter-spacing: 0.1em;
  color: var(--text-buried);
  padding-top: 4px;
}

.welcome-steps h2 {
  margin: 0 0 var(--spacing-sm);
  font-family: var(--font-mono);
  font-size: var(--size-title);
  font-weight: 600;
  letter-spacing: 0.14em;
}

.welcome-steps h2 a {
  color: var(--text-title);
  text-decoration: none;
  border-bottom: 1px solid var(--border-active);
}

.welcome-steps h2 a:hover {
  color: var(--text-title);
}

.welcome-steps p {
  margin: 0;
  color: var(--text-white);
  font-size: var(--size-body);
  line-height: 1.7;
}

.welcome-steps strong,
.welcome-pricing strong {
  color: var(--text-white);
  font-weight: 600;
}

.welcome-pricing {
  padding: var(--spacing-md) var(--spacing-lg);
  margin-bottom: var(--spacing-xl);
  background: var(--bg-inset);
  border: 1px solid var(--bg-inset);
  border-radius: var(--radius);
}

.welcome-pricing p {
  margin: 0;
  color: var(--text-white);
  font-size: var(--size-body);
  line-height: 1.7;
}

.welcome-actions {
  text-align: center;
}

.welcome-footnote {
  margin: var(--spacing-md) 0 0;
  font-family: var(--font-mono);
  font-size: var(--size-meta);
  color: var(--text-buried);
}

.welcome-footnote a {
  color: var(--text-dim);
}

/* Explanatory line under a section heading — the sentence that used to be the
   whole point of a page now that several pages sit stacked on one. */
.card-lede {
  font-size: var(--size-body);
  color: var(--text-white);
  line-height: 1.9;
  margin-bottom: var(--spacing-md);
}

/* ========================
   Dashboard grid
   Row 1 is the welcome banner and the app tiles as one full-width block; row 2
   is the two cards someone might have come here to change. Two columns rather
   than three, so nothing reads as an empty slot while only one app is connected.
   ======================== */
.dash-hero .dashboard-greeting {
  margin-bottom: var(--spacing-sm);
}

.dash-hero-apps {
  margin-top: var(--spacing-lg);
}

/* Greeting on the left, the unlock button squared off against it on the right.
   Wraps rather than squeezing, so on a narrow screen the button drops below the
   greeting instead of the two fighting over the same line. */
.dash-hero-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--spacing-lg);
  flex-wrap: wrap;
}

/* min-width: 0 lets a long name ellipsize inside the flex row rather than
   pushing the button off the card. */
.dash-hero-intro {
  min-width: 0;
}

/* The auto margin does nothing while the button shares a line with the greeting.
   It is for the wrapped case, where the button would otherwise drop to the left. */
.dash-hero-unlock {
  flex-shrink: 0;
  margin-left: auto;
}

/* The header indicator, reused above the greeting. Sits on its own line, so it
   needs clearance under it rather than beside it. */
.dash-hero-status {
  margin-bottom: var(--spacing-sm);
}

/* Equal columns, and stretch rather than start so both cards take the height of
   the taller one instead of each shrinking to its own copy. */
.dash-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--spacing-md);
  align-items: stretch;
  /* Stands in for the bottom margin the cards inside it no longer carry, so the
     row below still clears it. */
  margin-bottom: var(--spacing-md);
}

/* With the cards now the same height, push both buttons to the bottom edge so
   they line up instead of floating wherever the copy above them happens to end. */
.dash-cols > .card {
  display: flex;
  flex-direction: column;
  /* The grid gap does the spacing here, so the card's own bottom margin would
     only shave a stray strip off the stretched height. */
  margin-bottom: 0;
}

.dash-cols > .card .btn {
  margin-top: auto;
  align-self: flex-end;
}

@media (max-width: 768px) {
  /* Stacked, so the gap is what separates them now that the cards' own bottom
     margin is off. */
  .dash-cols {
    grid-template-columns: 1fr;
    gap: var(--spacing-md);
  }
}

/* The greeting now sits inside the hero card, which already fades in. Without
   this it would stage a second entrance of its own and visibly stutter. */
.card .dashboard-greeting.animate-in {
  opacity: 1;
  animation: none;
}

/* ========================
   Terminal frame
   ======================
   The T artwork (public/tt-frame-fin.svg, 1208 x 875) is a fixed, letterboxed
   canvas behind every page. .tt-screen is a scroll box laid over the screen
   opening in the bezel, so the header, the page and the footer all scroll
   inside the terminal rather than the window. The opening in the artwork
   runs from x 183 to 1025 and y 126 to 741; the percentages below are those
   edges. Two copies of the art bracket the page: tt-frame-fin.svg beneath it
   paints the whole thing including the dark screen panel, and
   tt-frame-over.svg above it is the same drawing with the panel cut out,
   so the bezel overlaps the page edges. The screen box reaches a few pixels
   under the bezel on every side, so there is no seam and the bezel curve is
   what clips the content. */
.tt-stage {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* The canvas is a tight crop of the T, so it is scaled to 0.755 of the
     window fit, which paints the T at the same size the wider canvas did at 1.2. */
  width: calc(0.755 * min(100vw, calc(100vh * 1920 / 1080)));
  aspect-ratio: 1207.96 / 875.4;
  z-index: 1;
}

.tt-frame-art {
  position: absolute;
  inset: 0;
  background: url('/tt-frame-fin.svg') center / 100% 100% no-repeat;
  pointer-events: none;
}

.tt-frame-over {
  position: absolute;
  inset: 0;
  background: url('/tt-frame-over.svg') center / 100% 100% no-repeat;
  pointer-events: none;
  z-index: 2;
}

.tt-screen {
  position: absolute;
  left: 14.8%;
  top: 14.0%;
  width: 70.0%;
  height: 71.0%;
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  z-index: 1;
}

/* A plain thin bar with no end buttons, so nothing sits at the bezel edge.
   Chromium and Safari take the pseudo-elements. They ignore them once
   scrollbar-width is set, so that property is reserved for Firefox, whose
   thin bar already draws without buttons. */
@supports not selector(::-webkit-scrollbar) {
  .tt-screen {
    scrollbar-width: thin;
    scrollbar-color: var(--text-almost-gone) transparent;
  }
}
.tt-screen::-webkit-scrollbar { width: 8px; }
.tt-screen::-webkit-scrollbar-track { background: transparent; }
.tt-screen::-webkit-scrollbar-thumb { background: var(--text-almost-gone); border-radius: 4px; }
.tt-screen::-webkit-scrollbar-button { display: none; height: 0; }

/* Below the tablet breakpoint the bezel would leave no usable screen, so the
   wrappers dissolve and the page lays out in the window as before. */
@media (max-width: 768px) {
  .tt-stage,
  .tt-screen {
    display: contents;
  }
  .tt-frame-art,
  .tt-frame-over {
    display: none;
  }
}
