:root {
  color-scheme: light;
  --bg: #eef2fb;
  --panel: #ffffff;
  --panel-soft: #f4f7ff;
  --ink: #14203a;
  --muted: #5c6a89;
  --line: #d7e0f5;
  --accent: #2947c9;
  --accent-strong: #1c2f6b;
  --warn: #b56a17;
  --danger: #c0405a;
  --success: #1a8f4c;
  --bubble: #2947c9;
  --bubble-ink: #ffffff;
  --shadow: 0 14px 36px rgba(20, 32, 70, 0.14);

  /* Royal silk blue: a deep-to-bright blue ramp used as a moving gradient
     so panels read like light catching folded silk rather than a flat fill. */
  --silk-1: #0c1740;
  --silk-2: #17297a;
  --silk-3: #2d47b8;
  --silk-4: #7093f4;
  --silk-gradient: linear-gradient(120deg,
    var(--silk-1) 0%, var(--silk-2) 22%, var(--silk-3) 45%,
    var(--silk-4) 58%, var(--silk-3) 70%, var(--silk-2) 85%, var(--silk-1) 100%);
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0a0f1f;
  --panel: #131b31;
  --panel-soft: #1a2440;
  --ink: #eef2ff;
  --muted: #a6b3d6;
  --line: #2a3866;
  --accent: #839bf7;
  --accent-strong: #aebdfb;
  --warn: #f0aa5d;
  --danger: #ff8da0;
  --success: #3ecb7e;
  --bubble: #2c3f8f;
  --bubble-ink: #ffffff;
  --shadow: 0 14px 36px rgba(0, 0, 0, 0.4);

  --silk-1: #050a1c;
  --silk-2: #101d52;
  --silk-3: #263e9c;
  --silk-4: #6483ee;
  --silk-gradient: linear-gradient(120deg,
    var(--silk-1) 0%, var(--silk-2) 22%, var(--silk-3) 45%,
    var(--silk-4) 58%, var(--silk-3) 70%, var(--silk-2) 85%, var(--silk-1) 100%);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0a0f1f;
    --panel: #131b31;
    --panel-soft: #1a2440;
    --ink: #eef2ff;
    --muted: #a6b3d6;
    --line: #2a3866;
    --accent: #839bf7;
    --accent-strong: #aebdfb;
    --warn: #f0aa5d;
    --danger: #ff8da0;
    --bubble: #2c3f8f;
    --bubble-ink: #ffffff;
    --shadow: 0 14px 36px rgba(0, 0, 0, 0.4);

    --silk-1: #050a1c;
    --silk-2: #101d52;
    --silk-3: #263e9c;
    --silk-4: #6483ee;
    --silk-gradient: linear-gradient(120deg,
      var(--silk-1) 0%, var(--silk-2) 22%, var(--silk-3) 45%,
      var(--silk-4) 58%, var(--silk-3) 70%, var(--silk-2) 85%, var(--silk-1) 100%);
  }
}

:root {
  /* Layout sizing lives in one place so the topbar/nav heights and the
     section-height math that depends on them can never drift out of sync.
     Safe-area insets default to 0px on devices without a notch/gesture bar
     (including the S22 Ultra), so this is inert there and only kicks in on
     hardware that actually reports a cutout or home-indicator inset. */
  --topbar-h: 84px;
  --nav-h: 58px;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);

  /* A visibly stronger, accent-tinted border for anything the user can
     actually interact with (search, composer, toggle buttons) — kept
     distinct from --line, which is used for plain content dividers/cards
     so controls are recognizable as controls at a glance. */
  --control-border: color-mix(in srgb, var(--accent), var(--line) 40%);
  --lift-shadow: 0 8px 20px rgba(20, 32, 70, 0.14);
}

* {
  box-sizing: border-box;
}

html, body {
  overscroll-behavior-y: none;
}

body {
  margin: 0;
  min-width: 320px;
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  letter-spacing: 0;
}

button,
input,
select {
  font: inherit;
}

button {
  cursor: pointer;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

.app-frame {
  min-height: 100vh;
  /* 100vh on mobile reports the height as if the address bar were hidden,
     even while it's actually showing — that's what was pushing the
     composer below the fold until you scrolled to reveal it. 100dvh
     tracks the real, currently-visible viewport as the address bar
     shows/hides; unsupported browsers just keep the 100vh line above. */
  min-height: 100dvh;
  display: grid;
  grid-template-rows: calc(var(--topbar-h) + var(--safe-top)) 1fr;
}

.topbar {
  background: var(--silk-gradient);
  background-size: 220% 220%;
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: var(--safe-top) calc(28px + var(--safe-right)) 0 calc(28px + var(--safe-left));
  box-shadow: var(--shadow);
  position: relative;
  z-index: 2;
}

.brand {
  display: flex;
  align-items: center;
  gap: 14px;
}

.brand-mark {
  width: 50px;
  height: 50px;
  display: grid;
  place-items: center;
  font-weight: 800;
  font-size: 25px;
}

.brand-wordmark {
  height: 51px;
  width: auto;
  display: block;
  position: relative;
  top: 2px;
}

.theme-toggle {
  border: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  color: #ffffff;
  font-size: 20px;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.theme-toggle {
  transition: transform 150ms ease, background 150ms ease;
}

.account-switcher {
  position: relative;
}

/* Same white capsule/pill design on every viewport now (originally phone-
   only, then extended to desktop per explicit request) — the plain person
   icon is hidden everywhere, replaced by the active account's own logo
   plus a count of how many are linked, both drawn on a white pill instead
   of the button's own color (Dropbox/Box/OneDrive's blue-toned logos
   blended into the plain blue button with nothing behind them). Updated
   live by updateAccountSwitcherToggleIcon() in app.js whenever the active
   provider changes — that function already runs on every viewport
   unconditionally, only the CSS used to gate visibility by breakpoint. */
.account-switcher-toggle-generic-icon {
  display: none;
}

.account-switcher-toggle {
  /* !important: this button shares .theme-toggle with the plain circular
     theme/sign-out buttons, and another .theme-toggle rule (920px block,
     below) also sets width/height — same-specificity, source-order-only
     overrides have bitten this exact button before, so pin the capsule
     shape down explicitly. */
  width: auto !important;
  height: 40px !important;
  padding: 0 14px 0 9px !important;
  border-radius: 999px !important;
  background: #fff !important;
  box-shadow: 0 2px 8px rgba(12, 20, 45, 0.22);
  display: inline-flex !important;
  align-items: center;
  justify-content: flex-start;
  gap: 7px;
}

.account-switcher-toggle-logo {
  display: grid;
  place-items: center;
}

.account-switcher-toggle-logo .account-badge-logo,
.account-switcher-toggle-logo .signin-provider-badge {
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
}

.account-switcher-toggle-logo .account-badge-logo svg {
  width: 21px;
  height: 21px;
}

/* Plain bold text inside the capsule (to the right of the logo), not a
   floating corner badge. */
.account-switcher-count {
  position: static;
  min-width: 0;
  height: auto;
  padding: 0;
  border-radius: 0;
  background: transparent;
  /* Fixed dark color, not var(--ink) — the capsule itself is always white
     regardless of theme, but --ink flips to near-white in dark mode and
     would go invisible against it. */
  color: #14203a;
  font-size: 14px;
  font-weight: 800;
  display: grid;
  place-items: center;
  line-height: 1;
}

/* Without this, the [hidden] attribute (toggled in loadAccountSwitcher
   based on how many accounts are linked) is silently ignored — same
   missing-guard bug found elsewhere this session. */
.account-switcher-count[hidden] {
  display: none;
}

.account-switcher-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 8;
  min-width: 230px;
  background: var(--panel);
  border: 1.5px solid var(--control-border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 10px;
  color: var(--ink);
  text-align: left;
}

.account-switcher-menu[hidden] {
  display: none;
}

.account-switcher-label {
  margin: 2px 0 8px !important;
  font-size: 11px !important;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

.account-switcher-list {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
}

.account-switcher-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  border-radius: 8px;
  background: var(--panel-soft);
  cursor: pointer;
  border: 1.5px solid transparent;
}

.account-switcher-item:hover {
  border-color: var(--control-border);
}

/* The account whose files are currently showing in Home/All Files —
   strict isolation means exactly one of these is ever "active" at a time. */
.account-switcher-item.is-active {
  border-color: var(--accent);
  background: var(--panel);
}

.account-switcher-item-active-badge {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 800;
  color: var(--accent-strong);
  letter-spacing: 0.02em;
}

/* A stale session for this one account — D1 remembers it was linked, but
   its refresh cookie is missing/dead. Doesn't affect any other account,
   including whichever one is still active — see switchToAccount in app.js. */
.account-switcher-item.needs-reconnect {
  border-color: var(--danger);
}

.account-switcher-item-reconnect-badge {
  flex-shrink: 0;
  font-size: 10px;
  font-weight: 800;
  color: var(--danger);
  letter-spacing: 0.02em;
}

.account-switcher-item-info {
  flex: 1 1 auto;
  min-width: 0;
}

.account-switcher-item-email {
  display: block;
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.account-switcher-item-provider {
  display: block;
  font-size: 11px;
  color: var(--muted);
}

.account-switcher-item-remove {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: var(--muted);
  background: var(--panel);
  border: 1.5px solid var(--line);
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease, transform 150ms ease;
}

.account-switcher-item-remove:hover,
.account-switcher-item-remove:focus-visible {
  background: color-mix(in srgb, var(--danger), transparent 88%);
  color: var(--danger);
  border-color: var(--danger);
  transform: scale(1.08);
}

.account-switcher-empty {
  font-size: 12px;
  color: var(--muted);
  padding: 4px 2px 8px;
}

.account-switcher-add {
  width: 100%;
  padding: 9px 0;
  border: 1.5px dashed var(--control-border);
  border-radius: 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--accent-strong);
  background: transparent;
}

.account-switcher-add:hover {
  border-color: var(--accent);
  background: var(--panel-soft);
}

.account-switcher-add-picker {
  display: flex;
  gap: 6px;
  margin-top: 6px;
}

/* Without this, the [hidden] attribute the JS toggles is silently ignored
   — an author-stylesheet display:flex rule with no [hidden] guard always
   overrides the browser's native hidden behavior, so this was actually
   visible the instant the menu opened regardless of whether "+ Add
   another account" was ever clicked. Same class of bug as the settings
   linked-accounts layout fixed earlier this session. */
.account-switcher-add-picker[hidden] {
  display: none;
}

.account-switcher-add-picker select {
  flex: 1 1 auto;
  min-width: 0;
  padding: 8px;
  border-radius: 8px;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--ink);
  font-size: 12px;
}

.account-switcher-add-confirm {
  flex-shrink: 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
}

.theme-toggle:hover {
  background: rgba(255, 255, 255, 0.28);
  transform: translateY(-1px);
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.topbar-signout:hover {
  background: color-mix(in srgb, var(--danger), rgba(255, 255, 255, 0.18) 30%);
}

.body-shell {
  min-height: 0;
  display: grid;
  grid-template-columns: 214px minmax(0, 1fr);
}

.app-nav {
  background: var(--silk-gradient);
  background-size: 220% 220%;
  color: #ffffff;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px 0;
}

.nav-item {
  min-height: 60px;
  border: 0;
  background: transparent;
  color: inherit;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 22px;
  margin-right: 14px;
  text-align: left;
  font-size: 16px;
  font-weight: 600;
  border-radius: 0 999px 999px 0;
}

.nav-item {
  transition: background 150ms ease, transform 150ms ease;
}

.nav-item:hover {
  background: rgba(255, 255, 255, 0.14);
  transform: translateY(-1px);
}

.nav-item.is-active {
  background: linear-gradient(135deg, var(--silk-3), var(--silk-4));
  box-shadow: 0 8px 20px rgba(12, 23, 64, 0.35);
}

.nav-icon {
  width: 26px;
  display: inline-grid;
  place-items: center;
  font-weight: 700;
  font-size: 18px;
}

@media (prefers-reduced-motion: no-preference) {
  .topbar,
  .app-nav {
    animation: silkShift 16s ease-in-out infinite alternate;
  }
}

@keyframes silkShift {
  0% { background-position: 0% 35%; }
  100% { background-position: 100% 65%; }
}

.main-panel {
  min-width: 0;
  background: var(--panel);
}

.app-section {
  display: none;
  /* A bounded height (not min-height) is required so the section itself
     scrolls internally rather than growing the whole page taller than the
     viewport — otherwise the topbar/composer/nav can end up pushed off
     screen or hidden behind the fixed nav on some devices. 100dvh (see
     .app-frame) is what actually fixes that on mobile; kept as a second
     declaration so unsupported browsers still get the 100vh fallback. */
  height: calc(100vh - var(--topbar-h) - var(--safe-top));
  height: calc(100dvh - var(--topbar-h) - var(--safe-top));
}

.app-section.is-active {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* Flex items with an explicit min-height lose the browser's default
   "never shrink below content size" protection — when total content
   exceeds the section's bounded height, they'd otherwise get compressed
   and their content would spill into whatever renders next. Nothing in
   these columns should ever shrink; the section's own overflow-y handles
   scrolling. message-stream is the deliberate exception (see its own rule). */
.app-section.is-active > * {
  flex-shrink: 0;
}

.app-section.is-active > .message-stream {
  flex-shrink: 1;
}

.home-section {
  position: relative;
}

.search-area {
  min-height: 64px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 22px;
  background: var(--panel-soft);
}

/* All Files scrolls as a whole section (see .app-section.is-active). The
   search bar AND the title/selection-counter row below it are wrapped
   together so they stay pinned as one unit while everything else
   (categories, filters, the list) scrolls underneath — a solid background
   so scrolled content doesn't show through the gap between them. */
.files-sticky-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--panel);
}

.search-box {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1.5px solid var(--control-border);
  border-radius: 12px;
  padding: 0 14px;
  background: var(--panel);
  transition: border-color 150ms ease, box-shadow 150ms ease, transform 150ms ease;
}

.search-box:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
  transform: translateY(-1px);
}

.search-box:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent), transparent 78%);
  transform: none;
}

.search-icon {
  color: var(--muted);
  font-size: 15px;
  flex-shrink: 0;
}

.search-box input {
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--ink);
  padding: 12px 0;
  font-size: 16px;
}

.search-box input:focus {
  outline: none;
}

.composer-label input,
.composer-label textarea,
select {
  width: 100%;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--ink);
  border-radius: 8px;
  padding: 12px 14px;
  min-height: 44px;
  transition: border-color 150ms ease, box-shadow 150ms ease, transform 150ms ease;
}

.composer-label textarea {
  font-family: inherit;
  resize: none;
  overflow-y: auto;
  max-height: 160px;
  line-height: 1.4;
}

/* Placeholder only — centered so the empty composer reads nicely on first
   open. Actual typed text stays left-aligned as normal (centering real
   multi-word notes while typing would look off). */
.composer-label textarea::placeholder {
  text-align: center;
}

.composer-label input:hover,
.composer-label textarea:hover {
  border-color: var(--accent);
}

/* Dropdowns get the full lift treatment like buttons — a text input doesn't,
   since shifting it while someone's about to type would feel jumpy. */
select:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
  transform: translateY(-1px);
}

.composer-label input:focus,
.composer-label textarea:focus,
select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent), transparent 78%);
}

.type-card {
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink);
  border-radius: 8px;
  padding: 10px 12px;
}

.filter-button,
.ghost-button,
.cleanup-tools button {
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--ink);
  border-radius: 8px;
  padding: 10px 12px;
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease, background 150ms ease;
}

.filter-button:hover,
.ghost-button:hover:not(:disabled),
.cleanup-tools button:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
  transform: translateY(-1px);
}

.filter-button {
  white-space: nowrap;
}

.filter-button.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: #ffffff;
}

.stream-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 24px;
}

.stream-header h1,
.files-section .panel-title h1 {
  font-size: 17px;
  margin-bottom: 1px;
}

.stream-header p {
  font-size: 12px;
  line-height: 1.3;
}

h1,
h2,
p {
  margin-top: 0;
}

h1 {
  margin-bottom: 4px;
  font-size: 30px;
  letter-spacing: 0;
}

.stream-header p,
.panel-title p,
.card-row span,
.cleanup-result p,
.file-subtext,
.meta-line {
  color: var(--muted);
}

.storage-pill {
  display: flex;
  align-items: baseline;
  gap: 4px;
  text-align: right;
  background: var(--panel-soft);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 12px;
  white-space: nowrap;
  flex-shrink: 0;
}

.storage-pill span {
  font-weight: 700;
  font-size: 13px;
}

.storage-pill small {
  font-size: 10px;
  color: var(--muted);
}

/* The pill doubles as a live selection count while selecting (see
   renderStorage) — "of 15 GB" tacked onto "3 selected · 5.2 MB" read as
   nonsense, so it's hidden for exactly that state. */
.home-section.is-selecting .storage-pill small {
  display: none;
}

.message-stream {
  flex: 1;
  min-height: 0; /* flex items default to min-height:auto, which blocks overflow:auto from ever kicking in */
  overflow: auto;
  padding: 12px 28px 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.home-loading {
  text-align: center;
  color: var(--muted);
  font-size: 14px;
  padding: 32px 16px;
}

.load-earlier-button {
  align-self: center;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--accent-strong);
  border-radius: 999px;
  padding: 8px 18px;
  font-size: 13px;
  font-weight: 700;
}

.load-earlier-button:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
}

.date-divider {
  align-self: center;
  color: var(--muted);
  font-size: 14px;
  margin-top: 4px;
}

.message-row {
  display: grid;
  grid-template-columns: 44px minmax(0, 760px);
  gap: 12px;
  align-items: end;
}

.message-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent-strong);
  color: #ffffff;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 800;
  flex-shrink: 0;
  overflow: hidden;
}

/* Real image/video preview (uploaded-this-session files only — the mock
   entries never had real bytes, so they always fall back to .type-badge). */
.thumb {
  object-fit: cover;
  display: block;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.4);
}

/* Colored, type-specific icon badge — used for every mock file and for any
   real upload without a renderable preview (documents, audio, archives). */
.type-badge {
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.18);
}

/* Holds the select checkbox + the file-type badge together as one grid
   cell (message-row only has 2 explicit columns: lead + bubble) — this is
   what keeps the row from breaking when a checkbox joins the badge. */
.message-lead {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  justify-self: center;
}

.message-row input.row-check {
  width: 22px;
  height: 22px;
  accent-color: var(--accent);
}

.message-bubble {
  justify-self: start;
  background: var(--panel);
  color: var(--ink);
  border: 1.5px solid var(--control-border);
  border-radius: 10px;
  padding: 11px 13px 10px;
  max-width: min(760px, 100%);
  position: relative;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

.message-bubble:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
}

.attachment-preview {
  display: block;
  width: 100%;
  max-width: 260px;
  max-height: 220px;
  object-fit: cover;
  border-radius: 8px;
  margin-bottom: 8px;
  background: var(--panel-soft);
}

/* Unfurled preview for a note that's just a shared link (Instagram, X,
   Facebook, or any regular website) — same idea/placement as
   .attachment-preview above, fetched server-side (see /api/link-preview
   in worker.js) since most sites don't expose their preview tags to a
   direct browser fetch. */
.link-preview-loading {
  font-size: 12px;
  color: var(--muted);
  padding: 6px 1px 2px;
  margin-bottom: 4px;
}

.link-preview-card {
  display: block;
  width: 100%;
  max-width: 360px;
  border: 1.5px solid var(--control-border);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 8px;
  background: var(--panel-soft);
  text-decoration: none;
  transition: border-color 150ms ease;
}

.link-preview-card:hover {
  border-color: var(--accent);
}

/* No image/title could be fetched (blocked, timed out, private post) —
   a smaller, dashed-border card so it visibly reads as "we tried, but
   couldn't unfurl this" rather than looking like a broken rich card. */
.link-preview-card--fallback {
  max-width: 260px;
  border-style: dashed;
}

.link-preview-card--fallback .link-preview-body {
  padding: 7px 11px;
}

.link-preview-card--fallback .link-preview-title {
  -webkit-line-clamp: 1;
}

.link-preview-image {
  display: block;
  width: 100%;
  max-height: 160px;
  object-fit: cover;
  background: var(--panel-soft);
}

.link-preview-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px 11px 9px;
}

.link-preview-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow-wrap: anywhere;
}

.link-preview-description {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.4;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow-wrap: anywhere;
}

.link-preview-site {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* Sits inline right before the title text (favicon-only when there's no
   bigger og:image to lead with) — vertical-align keeps it level with the
   text instead of sitting high/low against the title's own line-box. */
.link-preview-favicon {
  width: 14px;
  height: 14px;
  margin: 0 5px -2px 0;
  border-radius: 3px;
  object-fit: contain;
  vertical-align: middle;
}

.file-name {
  display: block;
  font-weight: 800;
  color: var(--ink);
  overflow-wrap: anywhere;
}

.message-text {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
}

.message-actions button.danger {
  border-color: color-mix(in srgb, var(--danger), transparent 55%);
  background: var(--panel);
  color: var(--danger);
}

/* Previously hidden on phone (<=460px) by an earlier explicit request —
   reversed by a later explicit request: the Home feed's Delete button for
   regular files/folders was the one row type missing it on mobile (text
   notes already showed Delete there). Shown on every viewport now, same as
   Download/Pin already were. */

.file-subtext {
  color: var(--muted);
  display: block;
  margin-top: 5px;
  font-size: 13px;
}

.meta-line {
  grid-column: 2;
  font-size: 13px;
  margin-top: -12px;
}

.message-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}

/* In-place note editing (see startEditingNote in app.js) — replaces the
   whole row's markup, so this needs to look reasonable dropped into
   either the Home feed's message-bubble layout or All Files' plainer
   table-row layout, not styled to assume one or the other. */
/* Spans the FULL row regardless of how many columns that row's own grid
   defines (.message-row: 2, icon + content; .table-row: 3, icon +
   content + actions) — this, not any width on the textarea itself, is
   what actually fixes the "tiny narrow box" bug: without it, the
   textarea/actions markup below lands as bare grid children and each one
   gets auto-placed into whichever narrow fixed-width track comes first
   (the icon column), not the wide content column. */
.note-edit-wrap {
  grid-column: 1 / -1;
  width: 100%;
}

.note-edit-textarea {
  display: block;
  width: 100%;
  box-sizing: border-box;
  min-height: 140px;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--ink);
  border-radius: 8px;
  padding: 10px 12px;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.5;
  resize: vertical;
}

@media (min-width: 640px) {
  .note-edit-textarea {
    min-height: 200px;
  }
}

.note-edit-textarea:focus {
  outline: none;
  border-color: var(--accent);
}

.note-edit-actions .primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

/* Download/Pin stay a solid blue capsule — that part looked good and stays;
   only the bubble's own background tint is going away. */
.message-actions button {
  border: 1px solid var(--accent);
  color: #ffffff;
  background: var(--accent);
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  transition: transform 150ms ease, background 150ms ease, box-shadow 150ms ease;
}

.message-actions button:hover {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  transform: translateY(-1px);
  box-shadow: var(--lift-shadow);
}

.message-actions button.is-pinned {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
}

.composer {
  position: sticky;
  bottom: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  gap: 10px;
  align-items: center;
  border-top: 2px solid var(--accent);
  background: var(--panel-soft);
  padding: 16px 18px;
  box-shadow: 0 -10px 24px rgba(20, 32, 70, 0.1);
}

.composer input[type="file"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.composer-label input,
.composer-label textarea {
  font-size: 18px;
}

.refresh-button {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--accent);
  border-radius: 10px;
  font-size: 18px;
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease;
}

.icon-button {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--accent);
  border-radius: 10px;
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease;
}

.icon-button:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
}

.sort-menu-wrap {
  position: relative;
  display: none; /* mobile-only trigger; desktop keeps #sortToggle as-is */
  flex-shrink: 0;
}

.select-exit-button {
  display: none;
  font-size: 22px;
  line-height: 1;
  font-weight: 400;
}

.sort-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 8;
  min-width: 170px;
  background: var(--panel);
  border: 1.5px solid var(--control-border);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sort-menu[hidden] {
  display: none;
}

.sort-menu button {
  border: 0;
  background: transparent;
  color: var(--ink);
  text-align: left;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
}

.sort-menu button:hover {
  background: var(--panel-soft);
}

.sort-menu button.is-active {
  color: var(--accent-strong);
  background: color-mix(in srgb, var(--accent), var(--panel-soft) 85%);
}

/* Wraps the composer's "+" button. On desktop it's just a transparent
   positioning box around the same button as before (folder stays visible
   as its own separate icon) — the popover only ever opens on mobile,
   gated in JS. On mobile the folder icon is hidden and "+" opens this
   popover instead, offering "Upload files" / "Upload folder". */
.attach-menu-wrap {
  position: relative;
}

.attach-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  z-index: 8;
  min-width: 180px;
  background: var(--panel);
  border: 1.5px solid var(--control-border);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.attach-menu[hidden] {
  display: none;
}

.attach-menu button {
  border: 0;
  background: transparent;
  color: var(--ink);
  text-align: left;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

.attach-menu button:hover {
  background: var(--panel-soft);
}

.refresh-button:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
  transform: translateY(-1px);
}

@keyframes refresh-spin {
  to { transform: rotate(360deg); }
}

/* Pull-to-refresh indicator: a normal block element with height 0 by
   default — dragging down while already scrolled to the top grows its
   height in JS, pushing the list down and revealing it, same feel as a
   native chat app's pull-to-refresh. */
.pull-indicator {
  height: 0;
  overflow: hidden;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
}

.pull-indicator .pull-icon {
  display: inline-block;
  line-height: 1;
  transition: transform 150ms ease;
}

.pull-indicator.is-ready .pull-icon {
  transform: rotate(180deg);
}

.pull-indicator.is-loading .pull-icon {
  animation: refresh-spin 700ms linear infinite;
}

.refresh-button.is-spinning {
  color: var(--accent);
  animation: refresh-spin 700ms linear infinite;
}

.drop-overlay {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: none;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 700;
  color: #ffffff;
  background: color-mix(in srgb, var(--accent), transparent 25%);
  border: 3px dashed rgba(255, 255, 255, 0.7);
  margin: 8px;
  border-radius: 16px;
  pointer-events: none;
}

.drop-overlay.is-active {
  display: flex;
}

.pending-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 10px 18px 0;
  background: var(--panel-soft);
}

/* Same missing-guard bug found elsewhere this session — without this the
   [hidden] attribute (toggled when there are no pending attachments to
   show) is silently ignored. */
.pending-attachments[hidden] {
  display: none;
}

.attachment-chip {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  border: 1px solid var(--control-border);
  background: var(--panel);
  border-radius: 999px;
  padding: 6px 8px 6px 12px;
  font-size: 12px;
  max-width: 220px;
}

/* The progress bar needs straight edges to sit flush along the bottom, so
   the pill shape relaxes to a rounded rect only while actively uploading. */
.attachment-chip[data-status="uploading"] {
  border-radius: 10px;
  max-width: 260px;
}

.attachment-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attachment-chip-status {
  color: var(--muted);
  white-space: nowrap;
}

.attachment-chip[data-status="uploading"] {
  border-color: var(--accent);
}

.attachment-chip[data-status="done"] {
  border-color: color-mix(in srgb, #1e9e6b, var(--control-border));
}

.attachment-chip[data-status="done"] .attachment-chip-status {
  color: #1e9e6b;
}

.attachment-chip[data-status="failed"] {
  border-color: var(--danger);
}

.attachment-chip[data-status="failed"] .attachment-chip-status {
  color: var(--danger);
}

.attachment-chip-remove {
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 16px;
  line-height: 1;
  padding: 2px;
  border-radius: 50%;
}

.attachment-chip-remove:hover {
  background: color-mix(in srgb, var(--danger), transparent 85%);
  color: var(--danger);
}

.attachment-chip-retry {
  border: 0;
  background: transparent;
  color: var(--accent);
  font-size: 16px;
  line-height: 1;
  padding: 2px;
  border-radius: 50%;
}

.attachment-chip-retry:hover {
  background: color-mix(in srgb, var(--accent), transparent 85%);
}

.attachment-chip[data-status="failed"] {
  border-color: color-mix(in srgb, var(--danger), transparent 55%);
}

.label-chip {
  display: inline-block;
  margin-top: 8px;
  padding: 3px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent), transparent 88%);
  border: 1px solid color-mix(in srgb, var(--accent), transparent 65%);
  color: var(--accent-strong);
  font-size: 14px;
  font-weight: 600;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attach-button,
.send-button {
  border: 0;
  min-height: 44px;
  border-radius: 8px;
  transition: transform 150ms ease, box-shadow 150ms ease, background 150ms ease;
}

.attach-button:hover,
.send-button:hover {
  transform: translateY(-1px);
  box-shadow: var(--lift-shadow);
}

.attach-button {
  width: 48px;
  background: var(--panel);
  color: var(--accent);
  font-weight: 800;
}

.send-button {
  background: linear-gradient(135deg, var(--silk-2), var(--silk-3) 60%, var(--silk-4));
  color: #ffffff;
  padding: 0 18px;
  font-weight: 700;
}

/* Composer's send button specifically (not the sign-in button, which
   shares .send-button for its color/gradient but needs to stay a full-
   width text button) — an icon, the paper-plane every chat app uses,
   same size/shape as the attach buttons beside it, so it sits inline on
   the composer row instead of needing its own standalone row. */
#sendButton {
  width: 48px;
  padding: 0;
  display: grid;
  place-items: center;
}

#sendButton:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.bulk-bar {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-top: 2px solid var(--accent);
  background: var(--panel-soft);
  padding: 12px 18px;
  box-shadow: 0 -10px 24px rgba(20, 32, 70, 0.1);
  z-index: 2;
}

.bulk-bar[hidden] {
  display: none;
}

.bulk-bar span {
  font-weight: 700;
  white-space: nowrap;
}

/* Desktop keeps the original single-line "N selected · size" look — the
   count and size are two elements now (for the mobile stacking below) but
   render inline with a separator, pixel-equivalent to the old combined
   text. Mobile overrides this to stack them (see the 920px block). */
.bulk-count {
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.bulk-count-size::before {
  content: "· ";
}

/* All Files' bulk-bar count gets the same accent emphasis as the new top
   pill, so it reads clearly against the rest of the bar either way. */
#filesBulkCount {
  color: var(--accent-strong);
  font-weight: 800;
}

.bulk-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.bulk-actions button {
  border: 1px solid var(--control-border);
  background: var(--panel);
  color: var(--ink);
  border-radius: 8px;
  padding: 9px 14px;
  min-height: 40px;
  font-weight: 600;
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease;
}

.bulk-actions button:hover:not(:disabled) {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
  transform: translateY(-1px);
}

.bulk-actions button.danger {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger), transparent 55%);
}

.bulk-actions button.danger:hover:not(:disabled) {
  border-color: var(--danger);
}

.bulk-actions button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.home-section.is-selecting .composer {
  display: none;
}

.panel-title,
.tool-layout,
.type-grid,
.table-actions,
.file-table,
.settings-list {
  margin-left: auto;
  margin-right: auto;
  width: min(1100px, calc(100% - 40px));
}

.panel-title {
  padding: 14px 0 6px;
}

/* All Files' title row doubles as a live selection counter once selecting
   — same idea as Home's storage pill, but scoped to this section only. */
.files-panel-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.selected-pill {
  background: color-mix(in srgb, var(--accent), var(--panel-soft) 82%);
  border-color: var(--accent);
}

.selected-pill span {
  color: var(--accent-strong);
  font-weight: 800;
  font-size: 14px;
}

.selected-pill[hidden] {
  display: none;
}

.panel-title h1 {
  margin: 0 0 2px;
}

.panel-title p {
  margin: 0;
}

/* All Files has no redundant "All files" heading (the nav already says
   that) — this summary line is the only label, so it reads a bit stronger
   than the usual muted subtitle text. */
p.files-summary-text {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}

.type-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.type-card {
  display: grid;
  gap: 3px;
  text-align: left;
  border-radius: 10px;
  background: var(--panel-soft);
  cursor: pointer;
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease;
}

.type-card strong {
  font-size: 12px;
  color: var(--muted);
  font-weight: 600;
}

.type-card span {
  font-size: 19px;
  font-weight: 800;
}

.type-card:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
  transform: translateY(-1px);
}

.type-card.is-active {
  border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent), transparent 70%);
}

.category-filter-panel {
  margin-left: auto;
  margin-right: auto;
  width: min(1100px, calc(100% - 40px));
  margin-bottom: 26px;
  border: 1.5px solid var(--control-border);
  border-radius: 10px;
  padding: 14px;
  background: var(--panel-soft);
}

.category-filter-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.category-filter-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Pinned-files drawer: a compact strip above the Home feed (max 4 items,
   enforced in JS) — a quick-glance shelf, not a second copy of the feed, so
   it never eats into the main scrolling area. The row pairs the strip with
   an "Unpin all" button — side by side on desktop, stacked on mobile. */
.pinned-drawer-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 2px 10px;
  flex-shrink: 0;
}

.pinned-drawer-row[hidden] {
  display: none;
}


.pinned-drawer {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  flex: 1;
  min-width: 0;
}

.pinned-chip {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  max-width: 220px;
  border-radius: 999px;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

.pinned-chip:hover {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
}

/* Two separate buttons, not a button-in-a-button — jump-to-file and unpin
   need independent click targets. */
.pinned-chip-main {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-weight: 600;
  font-size: 13px;
  padding: 6px 4px 6px 6px;
  cursor: pointer;
}

.pinned-chip-unpin {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  margin-right: 4px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  display: grid;
  place-items: center;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.pinned-chip-unpin:hover {
  background: color-mix(in srgb, var(--danger), transparent 85%);
  color: var(--danger);
}

.pinned-chip-icon {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex-shrink: 0;
  object-fit: cover;
  display: grid;
  place-items: center;
}

.pinned-chip-icon svg {
  width: 14px;
  height: 14px;
}

.pinned-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

@media (max-width: 920px) {
  .pinned-drawer-row {
    flex-direction: column;
    align-items: stretch;
  }

}

/* Brief flash on the row a pinned-drawer chip jumps to, so it's obvious
   which one you landed on. */
.message-row.is-highlighted .message-bubble {
  animation: pin-jump-flash 1.6s ease;
}

@keyframes pin-jump-flash {
  0%, 100% { box-shadow: none; }
  20%, 55% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent), transparent 25%); }
}

.attachment-chip-bar {
  display: block;
  flex-basis: 100%;
  height: 4px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}

.attachment-chip-bar > span {
  display: block;
  height: 100%;
  background: var(--accent);
  transition: width 150ms ease;
}

.type-image { background: linear-gradient(135deg, color-mix(in srgb, #3b6fe0 16%, var(--panel-soft)), var(--panel-soft)); }
.type-image span { color: #3b6fe0; }
.type-video { background: linear-gradient(135deg, color-mix(in srgb, #7c5cf2 16%, var(--panel-soft)), var(--panel-soft)); }
.type-video span { color: #7c5cf2; }
.type-audio { background: linear-gradient(135deg, color-mix(in srgb, #17a3a3 16%, var(--panel-soft)), var(--panel-soft)); }
.type-audio span { color: #17a3a3; }
.type-doc { background: linear-gradient(135deg, color-mix(in srgb, #d98c26 16%, var(--panel-soft)), var(--panel-soft)); }
.type-doc span { color: #d98c26; }
.type-folder { background: linear-gradient(135deg, color-mix(in srgb, #c9971e 16%, var(--panel-soft)), var(--panel-soft)); }
.type-folder span { color: #c9971e; }

.type-text { background: linear-gradient(135deg, color-mix(in srgb, #6b7789 16%, var(--panel-soft)), var(--panel-soft)); }
.type-text span { color: #6b7789; }

:root[data-theme="dark"] .type-image,
:root[data-theme="dark"] .type-video,
:root[data-theme="dark"] .type-audio,
:root[data-theme="dark"] .type-doc,
:root[data-theme="dark"] .type-folder,
:root[data-theme="dark"] .type-text {
  background-image: linear-gradient(135deg, color-mix(in srgb, currentColor 22%, var(--panel-soft)), var(--panel-soft));
}

.table-actions,
.tool-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.table-actions select,
.tool-controls select {
  width: auto;
  min-width: 190px;
}

.search-area select {
  width: auto;
  min-width: 170px;
}

.file-table {
  display: grid;
  gap: 8px;
  padding-bottom: 28px;
}

.table-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  border: 1px solid var(--line);
  background: var(--panel-soft);
  border-radius: 8px;
  padding: 12px;
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease;
}

.table-row:hover {
  border-color: var(--control-border);
  box-shadow: var(--lift-shadow);
  transform: translateY(-1px);
}

.table-row.is-selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent), var(--panel) 90%);
}

.table-row input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

/* Holds the select checkbox + the file-type badge together — table-row only
   has 3 explicit columns (lead, content, actions), so both need to live in
   one cell or the row breaks the same way message-row did. */
.table-row-lead {
  display: flex;
  align-items: center;
  gap: 8px;
}

.row-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}

.row-actions button {
  font-size: 12px;
  padding: 6px 10px;
  white-space: nowrap;
}

.select-all {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 12px;
  border: 1.5px solid var(--control-border);
  border-radius: 8px;
  color: var(--ink);
}

.select-all input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

/* Indeterminate ("some, not all, selected") needs to read as clearly
   different from fully checked, or a single selection can look like
   everything got selected. */
.select-all input:indeterminate {
  accent-color: var(--muted);
}

/* Desktop-only: a second "All" checkbox lives in the search bar next to
   Select, always visible there (checking it while not already selecting
   turns select mode on too — see handleHomeSelectAll/handleFilesSelectAll).
   On mobile the one in the bulk bar (at the bottom, within reach) is the
   only one — see the 920px breakpoint below. */
.select-all-top {
  display: inline-flex;
  border-color: var(--control-border);
}

.selected-size {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--muted);
  padding: 0 12px;
  white-space: nowrap;
}

.table-row strong {
  overflow-wrap: anywhere;
}

.table-row small {
  color: var(--muted);
}

.tool-layout {
  display: grid;
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
  padding-bottom: 36px;
}

.storage-card,
.cleanup-card,
.settings-list {
  border: 1px solid var(--line);
  background: var(--panel-soft);
  border-radius: 8px;
  padding: 10px 14px;
}

.storage-card {
  margin-bottom: 8px;
}

.card-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 4px;
}

.card-row strong {
  font-size: 13px;
}

.card-row span {
  display: block;
  margin-top: 2px;
  font-size: 12px;
}

/* Top line: real current Drive usage — a warning-red fill so it visually
   reads as "how much is filling up", distinct from the threshold slider
   below it (which stays the normal accent blue). */
.storage-meter {
  height: 7px;
  background: color-mix(in srgb, var(--line), transparent 20%);
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 8px;
}

.storage-meter span {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--danger), color-mix(in srgb, var(--danger), white 25%));
}

input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
  display: block;
  margin: 2px 0;
}

.switch {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  font-size: 13px;
}

.switch input {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

.cleanup-tools {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}

.cleanup-tools button.is-active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent), var(--panel) 84%);
}

.cleanup-result {
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: 8px;
  padding: 14px;
  margin-bottom: 12px;
}

.ghost-button.danger {
  color: var(--danger);
}

.ghost-button:disabled,
.filter-button:disabled,
.cleanup-tools button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.settings-list {
  display: grid;
  gap: 0;
}

.settings-list div {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 18px;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}

.settings-list div:last-child {
  border-bottom: 0;
}

.settings-list span {
  color: var(--muted);
  text-align: right;
}

.settings-connect {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: flex-end;
  flex-wrap: wrap;
}

/* Unlike every other .settings-list row (a label + one value, side by
   side), this one holds a variable-length list of linked accounts — needs
   to stack instead of forcing everything onto one cramped line. */
.settings-linked-accounts-row {
  display: flex !important;
  flex-direction: column;
  align-items: stretch !important;
  gap: 10px !important;
}

/* !important because .settings-list div (a broader descendant selector
   that also matches this element, being a nested div inside .settings-list)
   has higher specificity (class+element vs. just class) and would
   otherwise silently win with its own display:flex/justify-content —
   exactly the kind of cascade conflict already fixed once for
   .settings-linked-accounts-row above; missed applying the same fix here. */
.settings-linked-accounts {
  display: grid !important;
  justify-content: stretch !important;
  gap: 6px;
}

.settings-linked-empty {
  color: var(--muted);
  font-size: 13px;
}

/* !important throughout: same cascade conflict as .settings-linked-accounts
   above — .settings-list div (a broader descendant selector that also
   matches this element, being a nested div inside .settings-list) has
   higher specificity (class+element vs. just class) and was silently
   winning with its own padding/border-bottom, which is why only the
   .is-active row (two classes, genuinely higher specificity) showed any
   styling at all while every other row rendered as plain unstyled text. */
.settings-linked-row {
  display: flex !important;
  align-items: center !important;
  gap: 8px !important;
  padding: 8px !important;
  border-radius: 8px !important;
  background: var(--panel-soft) !important;
  border: 1.5px solid transparent !important;
}

.settings-linked-row.is-active {
  border-color: var(--accent);
}

/* The icon + provider name read as one paired unit on the left (matching
   how the Home greeting now pairs them too) — previously the icon stood
   alone at a much larger size than the small grey provider label way over
   on the right, which is what made the two sides look mismatched.
   !important throughout both of these: same cascade conflict as
   .settings-linked-row above, but this time it's the *phone-only* rules
   (.settings-list div { display: grid } and .settings-list span {
   justify-content: flex-start }, both inside the 460px media query) that
   silently won — the icon wasn't actually blurry, it was being forced
   into a CSS Grid cell narrower than its own fixed size (a well-known
   Grid quirk: a fixed-width child can still get squeezed by a track
   that's tighter than it, unlike in flex layout), which is what read as
   "misshapen." Missed checking that phone-specific block when this was
   first built, since it wasn't visible at desktop width. */
.settings-linked-left {
  display: flex !important;
  align-items: center !important;
  gap: 10px !important;
  justify-content: flex-start !important;
  min-width: 0;
}

.settings-linked-right {
  flex: 1 1 auto;
  min-width: 0;
  display: flex !important;
  align-items: center !important;
  justify-content: flex-end !important;
  gap: 8px !important;
  text-align: right;
}

.settings-linked-provider {
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}

.settings-linked-email {
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.settings-linked-active-tag {
  /* !important: .settings-list span (class+element, 0,1,1) otherwise beats
     this single-class selector (0,1,0) and silently overrides the color
     back to var(--muted) — the same cascade pattern hit repeatedly
     elsewhere on this page. */
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 800;
  color: var(--success) !important;
}

.threshold-hint {
  font-size: 12px;
  color: var(--muted);
  margin: 4px 0 0;
}

.toast {
  position: fixed;
  left: 50%;
  bottom: 18px;
  translate: -50% 20px;
  background: var(--ink);
  color: var(--bg);
  border-radius: 8px;
  padding: 12px 16px;
  box-shadow: var(--shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease, translate 180ms ease;
  max-width: min(90vw, 520px);
  z-index: 5;
}

.toast.is-visible {
  opacity: 1;
  translate: -50% 0;
}

@media (max-width: 920px) {
  /* Mobile keeps the "All" checkbox only in the bulk bar at the bottom
     (within thumb reach) — never duplicate it up in the search bar too. */
  .select-all-top {
    display: none !important;
  }

  /* Mobile-only control swaps: press-and-hold a row to select (see
     attachLongPressSelect in app.js) replaces the explicit Select button,
     and pull-to-refresh (Home only) replaces the manual refresh button
     there. All Files keeps its refresh button — it doesn't have pull-to-
     refresh. The compact sort-icon menu replaces the "Newest first" text
     toggle. None of this touches desktop. */
  #homeRefresh,
  #filesRefresh,
  #binRefresh,
  #homeSelectToggle,
  #filesSelectToggle,
  #binSelectToggle,
  #sortToggle,
  #allFilesSort {
    display: none !important;
  }

  .sort-menu-wrap {
    display: block;
  }

  /* The "Welcome OS" heading + item count are dropped on mobile to cut
     clutter — the pill still appears, but only while selecting (it
     doubles as the live selection counter; see renderStorage). */
  .home-section .stream-header {
    display: none;
  }

  .home-section.is-selecting .stream-header {
    display: flex;
  }

  .home-section.is-selecting .stream-header > div:first-child {
    display: none;
  }

  /* Mobile has no Select button to tap again to exit — the sort icon
     itself swaps for a clear "x" while selecting, a single obvious way
     back to the normal view without hunting for Cancel in the bulk bar. */
  .home-section.is-selecting .sort-menu-wrap,
  .files-section.is-selecting .sort-menu-wrap {
    display: none;
  }

  .home-section.is-selecting #homeSelectExit,
  .files-section.is-selecting #filesSelectExit,
  .bin-section.is-selecting #binSelectExit {
    display: grid;
    place-items: center;
    margin-left: auto;
  }


  .app-frame {
    grid-template-rows: auto 1fr;
  }

  :root {
    --topbar-h: 68px;
  }

  .topbar {
    min-height: 68px;
    padding: calc(10px + var(--safe-top)) calc(14px + var(--safe-right)) 10px calc(14px + var(--safe-left));
  }

  .brand-mark {
    width: 38px;
    height: 38px;
    font-size: 19px;
  }

  .brand-wordmark {
    height: 43.5px;
  }

  .theme-toggle {
    width: 38px;
    height: 38px;
    font-size: 17px;
  }

  .body-shell {
    grid-template-columns: 1fr;
  }

  .app-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;
    flex-direction: row;
    padding: 0 var(--safe-right) var(--safe-bottom) var(--safe-left);
    border-top: 1px solid rgba(255, 255, 255, 0.2);
  }

  .nav-item {
    flex: 1;
    min-height: var(--nav-h);
    padding: 6px 4px;
    margin-right: 0;
    border-radius: 0;
    display: grid;
    justify-items: center;
    gap: 4px;
    font-size: 12px;
  }

  .nav-icon {
    width: auto;
  }

  .app-section {
    /* topbar + fixed bottom nav reserved (including any safe-area insets
       those two now carry), so the section scrolls internally within
       exactly this box and can never render behind the fixed nav or push
       the page taller than the screen — on any device. dvh (see .app-frame
       for why) is what makes this actually match the real visible screen
       on mobile rather than the address-bar-hidden height. */
    height: calc(100vh - var(--topbar-h) - var(--safe-top) - var(--nav-h) - var(--safe-bottom));
    height: calc(100dvh - var(--topbar-h) - var(--safe-top) - var(--nav-h) - var(--safe-bottom));
  }

  .search-area {
    padding: 10px 12px;
  }

  .search-box input {
    font-size: 16px;
  }

  .filter-button {
    padding: 9px 10px;
    white-space: nowrap;
  }

  .stream-header {
    padding: 8px 14px;
  }

  h1 {
    font-size: 24px;
  }

  .storage-pill {
    padding: 5px 10px;
  }

  .storage-pill span {
    font-size: 12px;
  }

  .message-stream {
    padding: 10px 12px 18px;
    gap: 14px;
  }

  .message-row {
    grid-template-columns: 34px minmax(0, 1fr);
    gap: 9px;
  }

  .message-icon {
    width: 34px;
    height: 34px;
    font-size: 10px;
  }

  .message-bubble {
    max-width: 100%;
    padding: 10px 11px;
  }

  .meta-line {
    grid-column: 2;
    margin-top: -8px;
    font-size: 12px;
  }

  .composer {
    /* Send is inline now (see #sendButton), not its own standalone row —
       one row of icons instead of two, more room for the actual scrolling
       feed. Tighter padding/gap reclaims the width that row now needs.
       Folder is folded into the "+" popover on mobile (see #chooseFolder
       and .attach-menu below), so this is 3 tracks, not 4. */
    grid-template-columns: minmax(0, 1fr) 44px 44px;
    padding: 8px 6px;
    gap: 6px;
  }

  /* Folder upload moves into the "+" button's popover menu on mobile
     (.attach-menu-wrap / .attach-menu) instead of its own standalone icon —
     one less button competing for space in the composer row. Desktop keeps
     the plain, separate folder icon untouched. */
  #chooseFolder {
    display: none !important;
  }

  /* #labelInput is a <textarea>, not an <input> — this rule used to only
     list "input", so the label box was silently stuck at the desktop 18px
     size here, leaving no room for the (longer) placeholder to fit on one
     line in this compact box before getting clipped. */
  .composer-label input,
  .composer-label textarea {
    font-size: 16px;
    min-height: 44px;
  }

  /* Wrapping the actions to 2+ rows on a narrow phone risked pushing a
     button below what's actually visible once real browser chrome eats
     into the viewport (a synthetic full-height test doesn't show this).
     Keep the "All" checkbox and count fully visible, but let the action
     buttons scroll horizontally within their own space instead — that
     guarantees every action stays reachable regardless of exact device/
     browser chrome height, rather than gambling on vertical space. */
  .bulk-bar {
    flex-wrap: nowrap;
  }

  .bulk-bar > .select-all,
  .bulk-bar > span {
    flex-shrink: 0;
  }

  /* Count and size stack onto two short lines instead of one wide
     "N selected · size" line, so the freed-up horizontal space goes to
     the action buttons below instead. */
  .bulk-count {
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    line-height: 1.25;
    font-size: 13px;
  }

  .bulk-count-size {
    font-weight: 600;
    font-size: 11px;
    color: var(--muted);
  }

  .bulk-count-size::before {
    content: none;
  }

  .bulk-actions {
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
  }

  .bulk-actions button {
    flex-shrink: 0;
    padding: 9px 16px;
  }

  .panel-title,
  .tool-layout,
  .type-grid,
  .table-actions,
  .file-table,
  .settings-list {
    width: calc(100% - 24px);
  }

  .panel-title {
    padding-top: 12px;
  }

  .type-grid,
  .tool-layout {
    grid-template-columns: 1fr;
  }

  .type-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 6px;
    margin-bottom: 18px;
  }

  .type-card {
    min-height: 0;
    gap: 2px;
    padding: 8px 8px;
  }

  .type-card strong {
    font-size: 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .type-card span {
    font-size: 17px;
  }

  .cleanup-tools {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 6px;
  }

  .cleanup-tools button {
    padding: 10px 6px;
    font-size: 13px;
  }

  .table-row {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .row-actions {
    grid-column: 1 / -1;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
  }
}

@media (max-width: 460px) {
  .brand-wordmark {
    height: 39.5px;
  }

  /* The dropdown was anchored (right:0) to this toggle button's own
     narrow container — but the toggle isn't the rightmost element in the
     topbar (the theme toggle and sign-out buttons sit further right), so
     a 230px-wide menu anchored there could run off the left edge of a
     phone screen entirely, cutting off its own heading — exactly the
     "pushes toward the left" glitch. Switching to fixed positioning
     anchors it to the true screen edge (matching the topbar's own right
     padding/safe-area) instead of wherever this one button happens to
     sit, so it never overflows regardless of button position. */
  .account-switcher-menu {
    position: fixed;
    top: calc(var(--topbar-h) + var(--safe-top) + 4px);
    right: calc(16px + var(--safe-right));
    left: 16px;
    min-width: 0;
    width: auto;
  }

  /* Everything else in this row is hidden on mobile now (refresh, Select,
     the old sort toggle — see the 920px rules) except the sort icon (and
     the select-exit "x" while selecting) — one row, search box narrowing
     just enough to share it with the icon beside it, not a second row. */
  .search-area {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 8px;
  }

  .search-area .search-box {
    flex: 1 1 auto;
    min-width: 0;
  }

  .search-area .filter-button,
  .search-area select {
    width: 100%;
    min-width: 0;
  }

  .table-actions select,
  .table-actions button,
  .tool-controls select,
  .tool-controls button {
    width: 100%;
  }

  .stream-header {
    align-items: flex-start;
  }

  .type-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .cleanup-tools {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 5px;
  }

  .cleanup-tools button {
    padding: 9px 5px;
    font-size: 12px;
  }

  .settings-list div {
    display: grid;
  }

  .settings-list span,
  .settings-connect {
    text-align: left;
    justify-content: flex-start;
  }
}

/* The real first paint (see index.html) — neutral "checking" state shown
   before init() has determined signed-in vs. signed-out. Deliberately
   plain: no "Sign in" button, no file UI, just confirms the app is alive
   while the actual state gets resolved. */
.boot-screen {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: var(--silk-gradient);
  background-size: 220% 220%;
}

.boot-screen[hidden] {
  display: none;
}

.boot-screen-logo {
  width: min(220px, 60vw);
  height: auto;
}

.boot-screen-status {
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  opacity: 0.85;
}

.signin-gate {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  /* overflow-y:auto + margin:auto on the child (not align-items/justify-
     content:center) — the card grew taller once the provider list, the
     tagline, and the CTA line were all added, and on a real phone's
     actually-visible height (shorter than a synthetic full-height test
     window) it can now exceed the screen. A fixed-position element with
     align-items:center and no overflow handling traps that overflow with
     literally no way to scroll to it; margin:auto centers it the same way
     when it fits, but scrolls cleanly in both directions when it doesn't. */
  overflow-y: auto;
  background: var(--silk-gradient);
  background-size: 220% 220%;
  padding: 24px;
}

.signin-card {
  width: min(360px, 100%);
  margin: auto;
  background: var(--panel);
  border-radius: 16px;
  padding: 36px 28px;
  text-align: center;
  box-shadow: 0 24px 60px rgba(10, 15, 40, 0.35);
}

/* Wider on desktop specifically — 360px (the mobile-appropriate width)
   read as noticeably small/cramped on a real desktop window. Mobile is
   untouched. */
@media (min-width: 640px) {
  .signin-card {
    width: min(560px, 100%);
    padding: 44px 40px;
  }
}

.brand-mark img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* The decorative banner now lives full-bleed behind the whole sign-in
   screen (see .signin-gate); the card stays plain white with just the
   wordmark + prompt. */
.signin-card-logo {
  display: block;
  height: 56px;
  width: auto;
  margin: 0 auto 20px;
}

.signin-card p {
  color: var(--muted);
  font-size: 14px;
  margin-bottom: 20px;
}

.signin-tagline {
  color: var(--accent-strong) !important;
  font-size: 15px !important;
  font-weight: 700;
  line-height: 1.35;
  margin-bottom: 12px !important;
}

.signin-cta {
  margin: 18px 0 0 !important;
  font-size: 15px !important;
  line-height: 1.5;
  color: var(--muted);
}

.signin-faq-link {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  font-weight: 700;
  color: var(--accent-strong);
  text-decoration: underline;
}

/* --- Standalone FAQ page (faq.html) ------------------------------------ */

.faq-page {
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--silk-gradient);
  background-size: 220% 220%;
  padding: 24px 16px 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.faq-header {
  width: 100%;
  max-width: 720px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 24px;
}

.faq-back {
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  opacity: 0.9;
}

.faq-back:hover {
  opacity: 1;
  text-decoration: underline;
}

.faq-logo {
  height: 28px;
  width: auto;
}

.faq-main {
  width: 100%;
  max-width: 720px;
  background: var(--panel);
  border-radius: 20px;
  box-shadow: var(--shadow);
  padding: 32px 28px;
}

.faq-main h1 {
  margin: 0 0 8px;
  font-size: 26px;
  color: var(--ink);
}

.faq-intro {
  margin: 0 0 24px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.6;
}

.faq-list {
  display: grid;
  gap: 10px;
}

.faq-item {
  border: 1.5px solid var(--line);
  border-radius: 12px;
  padding: 14px 16px;
  background: var(--panel-soft);
}

.faq-item summary {
  cursor: pointer;
  font-weight: 700;
  color: var(--ink);
  font-size: 15px;
  line-height: 1.4;
}

.faq-item summary::marker {
  color: var(--accent);
}

.faq-answer {
  margin-top: 10px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.6;
}

.faq-answer ol {
  margin: 8px 0 0;
  padding-left: 20px;
}

.faq-answer li {
  margin-bottom: 4px;
}

.signin-note {
  margin-top: 14px;
  margin-bottom: 0 !important;
  min-height: 18px;
  color: var(--danger) !important;
}

/* Other providers, listed for awareness before they're actually wired up
   — the free-tier size is real, useful information even for a provider
   you can't sign into yet (see index.html comment: enabling one later is
   just removing "coming soon" + pointing the click at its /login route). */
.signin-more-label {
  margin: 22px 0 10px !important;
  font-size: 12px !important;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  text-align: left;
}

/* Decorative — "we work with these providers", not individually
   clickable. The actual choice happens in .signin-provider-select below;
   these badge classes are shared with the account-switcher's connected-
   accounts list (see .account-switcher-item), so they stay defined once. */
.signin-brand-strip {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
}

/* Real logo on a light chip reads as an actual brand mark, not a
   placeholder avatar — the flat colored-square-with-a-letter treatment
   this replaced looked more like a generic icon set than real brands.
   Now a real link (each opens that provider's own sign-up page), so it
   needs link resets (no underline) plus a visible hover/focus state. */
.signin-brand-chip {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--panel);
  border: 1.5px solid var(--line);
  box-shadow: 0 1px 3px rgba(10, 15, 40, 0.08);
  text-decoration: none;
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease;
}

.signin-brand-chip:hover,
.signin-brand-chip:focus-visible {
  border-color: var(--accent);
  box-shadow: var(--lift-shadow);
  transform: translateY(-2px);
}

.signin-brand-chip--letter {
  font-size: 16px;
  font-weight: 800;
  text-decoration: none;
}

/* Was previously (wrongly) placed inside the earlier @media block above
   the base .signin-brand-chip rule — since both had equal specificity,
   source order made the later, unconditional base rule win at every
   width, silently overriding the desktop sizing. Keeping the override
   here, after the base rule, is what actually makes it take effect. */
@media (min-width: 640px) {
  .signin-brand-chip {
    width: 60px;
    height: 60px;
    border-radius: 14px;
  }

  .signin-brand-chip svg {
    width: 32px;
    height: 32px;
  }

  .signin-brand-chip--letter {
    font-size: 26px;
  }
}

.signin-select-label {
  display: block;
  margin-bottom: 10px;
}

.signin-provider-select {
  width: 100%;
  border: 1.5px solid var(--control-border);
  background: var(--panel);
  color: var(--ink);
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 14px;
  font-weight: 600;
}

.signin-provider-select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent), transparent 78%);
}

.signin-provider-badge {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 800;
  color: #fff;
}

/* Real-logo alternative to .signin-provider-badge (see providerBadgeMarkup
   in app.js) — a neutral round base since the logos themselves carry their
   own brand color, unlike the plain colored-letter fallback. */
/* The "Welcome OS — <provider>" bit next to the Home greeting — reuses
   providerBadgeMarkup's real-logo badge, just sized down to sit inline
   with the heading text instead of at its normal list-row size. */
.home-greeting-provider {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* 1em matches "Welcome OS" exactly (desktop, per explicit request); the
     phone-only override below keeps the earlier 0.85em sizing there. */
  font-size: 1em;
  font-weight: 700;
  color: var(--muted);
  vertical-align: middle;
  margin-left: 6px;
}

.home-greeting-provider .account-badge-logo,
.home-greeting-provider .signin-provider-badge {
  width: 36px;
  height: 36px;
}

.home-greeting-provider .account-badge-logo svg {
  width: 24px;
  height: 24px;
}

/* Desktop only: the provider name (e.g. "Box") sits inside an
   inline-flex box centered against the logo, not against "Welcome OS"'s
   own text baseline, so it reads slightly low. Nudge just the text (not
   the logo) up to land on the same line — cancelled back to 0 on phone
   below, where this wasn't reported as an issue. */
.home-greeting-provider-text {
  position: relative;
  top: -1px;
}

/* Phone keeps the earlier, smaller sizing (0.85em text, 30px/19px logo) —
   this change was requested for desktop only. */
@media (max-width: 460px) {
  .home-greeting-provider-text {
    top: 0;
  }

  .home-greeting-provider {
    font-size: 0.85em;
  }

  .home-greeting-provider .account-badge-logo,
  .home-greeting-provider .signin-provider-badge {
    width: 30px;
    height: 30px;
  }

  .home-greeting-provider .account-badge-logo svg {
    width: 19px;
    height: 19px;
  }
}

/* No circular background/border, per explicit request — the logo just
   sits directly on whatever it's placed against, everywhere it's used
   (settings list, account switcher, Home greeting). */
.account-badge-logo {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
}

.account-badge-logo svg {
  width: 24px;
  height: 24px;
}

.signin-provider-badge--google { background: #4285f4; }
.signin-provider-badge--dropbox { background: #0061ff; }
.signin-provider-badge--box { background: #0061d5; }
.signin-provider-badge--onedrive { background: #0364b8; }
.signin-provider-badge--pcloud { background: #17baeb; }
.signin-provider-badge--koofr { background: #00a99d; }
.signin-provider-badge--mediafire { background: #0296e5; }
.signin-provider-badge--zoho { background: #e42527; }

/* Partial OneDrive Bin coverage must remain readable on small screens. */
.bin-provider-notice {
  margin: 8px 12px 16px;
  font-size: 0.82rem;
  font-weight: 400;
  line-height: 1.5;
}


/* Selection exit must remain visible in both themes. */
#homeSelectExit,#filesSelectExit,#binSelectExit {background:#ffe4b8;color:#492600;border:2px solid #bf7000;border-radius:12px;min-width:44px;min-height:44px;box-shadow:0 0 0 2px var(--paper);font-weight:800;}
#homeSelectExit:focus-visible,#filesSelectExit:focus-visible,#binSelectExit:focus-visible {outline:3px solid #ffad32;outline-offset:3px;}

.preview-badge{position:relative;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.preview-badge-image{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}

.attachment-chip[data-status="ready"]{border-color:#24835b}.attachment-chip[data-status="ready"] .attachment-chip-status{color:var(--ink);font-weight:700}

/* Customer identity gate */
.customer-locked> :not(#customerGate):not(#requestMeter):not(.customer-safety-dialog){display:none!important}
.customer-gate{min-height:100dvh;display:grid;place-items:center;padding:32px 20px;background:var(--silk-gradient);color:#18264c;overflow:auto}
.customer-card{box-sizing:border-box;width:min(100%,520px);padding:32px 36px;border:1px solid #dce1f2;border-radius:26px;background:#fff;box-shadow:0 24px 70px #080f4033}
.customer-logo{display:block;width:180px;max-width:65%;height:auto;margin:0 auto 26px}
.customer-eyebrow{font-size:11px;font-weight:800;letter-spacing:.14em;color:#4559a3}
.customer-card h1{font-size:30px;letter-spacing:-.03em;margin:8px 0 12px}
.customer-intro,.customer-privacy,.customer-help{font-size:14px;line-height:1.6;color:#53617c}
.customer-providers{display:flex;flex-wrap:wrap;gap:8px;margin:20px 0 12px}
.customer-providers span{padding:7px 10px;border:1px solid #dbe2f3;border-radius:9px;background:#f4f6fc;font-size:12px;font-weight:750;color:#283b79}
.customer-privacy{font-size:12px;margin-bottom:24px}
.customer-card button{font:inherit;font-weight:700;min-height:44px;padding:10px 14px;margin:6px 0;border:1px solid #ccd5ee;border-radius:11px;cursor:pointer;color:#283b79;background:#f4f6fc}
.customer-card button:disabled{opacity:.55;cursor:wait}
.customer-tabs{display:flex;gap:5px;background:#f0f3fa;border-radius:12px;padding:4px;margin-bottom:20px}
.customer-tabs button{flex:1;background:transparent;border-color:transparent;margin:0}
.customer-tabs button[aria-pressed=true]{background:#fff;border-color:#d8dff1;box-shadow:0 2px 6px #172d6510}
.customer-google{width:100%;background:#fff!important}
.customer-help{font-size:12px;margin:6px 0 12px}
.customer-card form{display:grid;gap:7px}
.customer-card label{display:grid;gap:7px;font-size:13px;font-weight:750;margin:6px 0}
.customer-card input{min-width:0;padding:12px;border:1px solid #c5cfe5;border-radius:10px;font:inherit;background:#fff;color:#18264c}
.customer-card :is(button,input):focus-visible{outline:3px solid #7e99ef;outline-offset:3px}
.customer-card .customer-primary{color:#fff;background:#293fa1;border-color:#293fa1}
.customer-divider{display:flex;align-items:center;gap:12px;margin:18px 0;font-size:12px;color:#66738f}
.customer-divider:before,.customer-divider:after{content:'';height:1px;background:#e0e5f0;flex:1}
.customer-status{font-size:13px;line-height:1.6;font-weight:700;min-height:20px;margin-bottom:0}
.customer-verification{padding:18px;background:#f2f5fe;border-radius:14px;line-height:1.6}
.customer-verification h2{margin-top:0;font-size:21px}.customer-verification button{width:100%}
.customer-card [hidden],.signin-card [hidden]{display:none!important}
#customerIdentity{display:grid;gap:10px;padding:16px;margin-top:22px;border:1px solid var(--line);border-radius:12px;overflow-wrap:anywhere;font-size:13px}
#customerIdentity button{justify-self:center;padding:9px 14px;min-height:40px;border-radius:9px;border:1px solid var(--line);background:var(--panel);color:var(--ink);font:inherit;cursor:pointer}
#driveConnectTitle{font-size:24px;line-height:1.25;margin:16px 0}
@media(max-width:480px){.customer-gate{padding:16px 12px}.customer-card{padding:26px 22px;border-radius:20px}.customer-card h1{font-size:27px}}
