/* =====================================================================
   styles.css — the only V2-authored stylesheet

   Everything visual comes from the V1 theme snapshot (/shared, /apps/files,
   /apps/users). This file carries just three things the snapshot cannot:
     1. the login card (V1's login lives in a page V2 does not serve);
     2. the window-chrome geometry that V1 keeps INLINE in jessos.html
        (never snapshotted) — window frame, titlebar, traffic-light buttons;
     3. theme-token skins for the V2-only feature dialogs, so they read as
        native JessOS surfaces rather than generic <dialog> boxes.
   ===================================================================== */

:root { color-scheme: dark; }
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; min-height: 100vh; }
body {
  font: 14px/1.45 "Ubuntu", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: var(--text-primary);
  /* Same desktop wallpaper V1 sets inline on <body> in jessos.html. */
  background: url('/assets/theme/wallpapers/ubuntuwallpaper2.webp') center/cover no-repeat fixed, #2c001e;
}
.app-shell { min-height: 100vh; }

/* Boot splash — the neutral state between page load and the resolved session
   (workspace or login). Sits on the same wallpaper as the desktop, so a refresh
   reads as "the desktop is loading", never a login-card flash. */
.v2-boot-splash{position:fixed;inset:0;z-index:5;display:flex;align-items:center;justify-content:center;background:url('/assets/theme/wallpapers/ubuntuwallpaper2.webp') center/cover no-repeat fixed,#2c001e}
.v2-boot-spinner{width:34px;height:34px;border-radius:50%;border:3px solid #ffffff33;border-top-color:#f57c2a;animation:v2-boot-spin .8s linear infinite}
@keyframes v2-boot-spin{to{transform:rotate(360deg)}}

/* ===================== LOGIN (exact V1 visual language) =====================
   Isolated here so V2 never loads V1 code. This is the project's quality bar
   for pixel fidelity; leave it untouched. */
.v2-login-root{position:fixed;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:url('/assets/theme/wallpapers/ubuntuwallpaper2.webp') center/cover no-repeat,#000;color:#f5f5f5;font-family:system-ui,-apple-system,BlinkMacSystemFont,"Ubuntu",sans-serif;font-size:14px}
.v2-login-time{position:absolute;top:10px;left:50%;transform:translateX(-50%);font-size:13px;text-shadow:0 1px 2px #000c;opacity:.9}
.v2-login-card{width:100%;max-width:440px;border-radius:14px;background:rgba(38,12,50,.55);border:1px solid #fff3;box-shadow:0 22px 55px #000b;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);padding:20px 24px 18px;display:flex;flex-direction:column;gap:14px}
.v2-login-user-row{display:flex;align-items:center;gap:14px;margin-bottom:6px}
.v2-login-avatar{width:56px;height:56px;border-radius:50%;overflow:hidden;border:2px solid #ffffffa6;box-shadow:0 0 0 2px #0008;flex-shrink:0;background:#0006;display:flex;align-items:center;justify-content:center}
.v2-login-avatar img{width:48px;height:48px;object-fit:contain}
.v2-login-identity{display:flex;flex-direction:column;gap:2px}
.v2-login-username-label{font-size:13px;font-weight:500}
.v2-login-portal-label{font-size:11px;color:#ccc}
.v2-login-fields{display:flex;flex-direction:column;gap:10px}
.v2-login-field{display:flex;flex-direction:column;gap:4px}
.v2-login-field label{font-size:11px;color:#ccc}
.v2-login-input{height:32px;border-radius:8px;border:1px solid #ffffff40;background:#0a03148c;color:#f5f5f5;padding:0 10px;font-size:13px}
.v2-login-input:focus{outline:1px solid #f26722;outline-offset:1px;border-color:#f26722}
.v2-login-actions{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-top:6px}
.v2-login-remember{display:flex;align-items:center;gap:6px;font-size:11px;color:#ccc;margin-right:auto}
.v2-login-remember input{width:14px;height:14px;accent-color:#f26722}
.v2-login-button{min-width:120px;height:34px;border-radius:999px;border:1px solid #000b;background:linear-gradient(to right,#f57c2a,#f49a3c);color:#fff;font-size:13px;font-weight:600;display:flex;align-items:center;justify-content:center;gap:6px;cursor:pointer;box-shadow:0 2px 6px #000a}
.v2-login-button:disabled{opacity:.65;cursor:default;box-shadow:none}
.v2-login-error{min-height:18px;font-size:11px;color:#ff5555;margin-top:4px}
.v2-login-footer{margin-top:4px;font-size:11px;color:#ccc;display:flex;justify-content:space-between;align-items:center;opacity:.9}
.v2-login-footer .jess{color:#c45307}
.v2-login-footer .os{color:#cca000}
@media(max-width:480px){.v2-login-card{padding:16px 14px 14px}}

/* ===================== DESKTOP + WINDOW CHROME =====================
   Ported from jessos.html's inline <style> (which the visual snapshot does
   not include). The workspace runs inside the same geometry as the V1 shell. */
#workspace-view{position:fixed;inset:0}
.workspace .desktop{position:fixed;inset:0;display:flex;flex-direction:column}

#window{
  position:fixed;
  top:calc(34px + 75px);
  left:calc(var(--dock-width,60px) + 100px);
  right:100px;
  bottom:20%;
  display:flex;
  flex-direction:column;
  border-radius:6px;
  box-shadow:var(--window-shadow);
  overflow:hidden;
  background:var(--window-bg);
}
#window-titlebar{
  height:38px;flex-shrink:0;background:var(--headerbar-bg);color:var(--headerbar-text);
  display:flex;align-items:center;justify-content:space-between;padding:0 12px;gap:12px;
  border-bottom:1px solid rgba(0,0,0,.2);text-shadow:var(--text-shadow);
}
#window-icon{width:20px;height:20px;flex-shrink:0}
.window-title-left{display:flex;align-items:center;gap:8px}
#window-title{font-weight:500;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.window-spacer{flex:1}

/* Traffic-light controls: fixed 14px squares with a normal/hover image swap.
   Without this the button images render at natural size and stack into dots. */
.window-controls{display:flex;gap:6px}
.window-btn{width:14px;height:14px;padding:0;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center}
.window-btn img{width:14px;height:14px;display:block}
.window-btn .btn-normal{display:block}
.window-btn .btn-hover{display:none}
.window-btn:hover .btn-normal{display:none}
.window-btn:hover .btn-hover{display:block}

#window-body,#logs-window-body{flex:1;background:var(--bg-view);display:flex;flex-direction:column;min-height:0;position:relative;overflow:hidden}
#window-body[hidden],#logs-window-body[hidden]{display:none}

/* Maximize fills below the top bar, flush to the dock (matches V1). */
#window{transition:transform .2s ease}
#window.maximized{top:34px;left:var(--dock-width,60px);right:0;bottom:0;border-radius:0}
#window.window-hiding{transform:scale(0);opacity:0}

/* Symbolic (monochrome) icons must read on the dark theme; in the sidebar only
   the V2-only Shared/Trash entries are symbolic (Home uses the full-colour
   folder icon).
   NOT every symbolic icon is black, though. The Adwaita set ships two fills:
   MENU/list icons (the apps/files/img symbolic set used in menus) are #2e3436
   (dark) and DO need inverting, but the three TOOLBAR images — open-menu,
   system-search, mail-message-new — already ship at #ececec (light). The old
   blanket `.files-toolbar-btn img{filter:invert(1)}` therefore inverted the
   hamburger the WRONG way and rendered it black; search/notify are in
   BASE_HIDE so only the hamburger showed the bug. Toolbar images keep the
   shared .85 opacity (matching the currentColor Back/Refresh/Home svgs) but
   no longer invert. */
.files-toolbar-btn img{opacity:.85}
.files-sidebar-item .sym-icon{filter:invert(1);opacity:.85}
.files-hamburger-icon,.files-context-menu-icon{filter:invert(1);opacity:.85}

/* ===================== TOOLBAR DOWNLOAD (V2 layout) =====================
   files.js rehomeActionBar() moves #toolbarDownload into .files-toolbar-left
   right after #navHome; the container's own gap:4px supplies "the same spacing
   the toolbar buttons use between each other", so no margin is set here. The
   button keeps its V1 form (accent pill, icon + "Download" label); only its
   box is aligned to the 32px toolbar row — the snapshot's 7px vertical padding
   plus a 14px icon made it 30px and optically high against the icon buttons. */
/* margin-right: 4px flex gap + 8 = 12px to the hamburger, mirroring the
   hamburger's 12px toolbar-padding distance to the window edge (Jess). */
#toolbarDownload.files-action-btn{height:32px;padding:0 12px;line-height:1;margin-right:8px}
/* The toolbar now anchors drag-pill.js's WebKit static pill (the action bar
   used to). */
.files-toolbar{position:relative}
/* Selection count re-homed into the status bar: match its siblings there
   (.files-status-stats) rather than the old action-bar treatment.
   The snapshot's responsive block (files.css @media max-width:800px) hides
   .files-selection-info !important — it was crowding the old action bar at
   narrow widths. In the status bar there is nothing to crowd, and the count is
   the only feedback for a selection you cannot see, so that hide is undone. */
.files-status-left #selectionInfo{display:inline!important;margin-left:8px;font-size:11px;color:var(--text-muted);white-space:nowrap}
/* Belt and braces: the retired row must never reappear if some future code
   path clears its inline display. */
.files-action-bar{display:none!important}

/* Compact row density (view-modes.js). */
.files-compact .files-row{padding-top:3px;padding-bottom:3px}
.files-compact .files-icon{width:20px;height:20px}
.files-compact .files-name-text{font-size:12px}
.files-compact .files-row-download-btn{width:22px;height:22px}

/* Cut items (clipboard.js) dim until pasted. */
.files-row.cut{opacity:.5}

/* ===================== DRAG FEEDBACK (native-calm) =====================
   Jess, 2026-08-26: the old feedback read as "web" — an accent ring on the
   armed row, an animated countdown fill sweeping across it, and a floating
   pill following the cursor. Finder and Nautilus do none of that: the folder
   under the drag simply looks SELECTED, and any wording lives in the window's
   status bar (features/transfers.js writes it there now).

   1) Silence the spring countdown everywhere — the snapshot's fill
      (apps/files/files.css `spring-load-fill`) for rows and sidebar items, and
      the crumb fill this file used to add. spring-loaded.js still sets
      `.spring-loading` and `--spring-delay` (harness contract + future use);
      only the paint goes quiet, so an ARMED element is indistinguishable from
      a plain drop target.

   2) Drop targets (rows, sidebar items, crumbs) take exactly the selected-row
      tint — files.css `.files-row.selected` is rgba(212,85,0,.25), the
      desaturated orange. No ring, no outline, no transition flourish.

   `.spring-loading` is listed in BOTH roles on purpose. Its snapshot rule uses
   the `background` SHORTHAND, which zeroes background-color, so the tint has
   to be restated for the armed element anyway — and some armed elements never
   get `.drop-target` at all (nothing marks a sidebar item or a crumb during an
   OS upload drag), which under a pure "animation:none" would have left them
   with no feedback whatsoever. Armed and hovered therefore paint identically,
   which is the whole point. */
.files-row.folder.drop-target,
.files-row.folder.spring-loading,
.files-sidebar-item.drop-target,
.files-sidebar-item.spring-loading,
.files-breadcrumb-item.drop-target,
.files-breadcrumb-item.spring-loading{
  background-color:rgba(212,85,0,.25);
  background-image:none;
  box-shadow:none;
  outline:none;
  transition:none;
  animation:none;
}

/* Breadcrumb width measurement (breadcrumb-overflow.js). The snapshot lets
   crumbs shrink and ellipsize (flex-shrink:1 + text-overflow), so a plain
   offsetWidth read reports the SHRUNK width and can never tell us whether the
   trail really fits. This class is added and removed inside one synchronous
   task — never painted — so each crumb reports its natural width. */
#breadcrumb.bc-measuring{max-width:none}
#breadcrumb.bc-measuring .files-breadcrumb-item{flex-shrink:0;min-width:auto;max-width:none;overflow:visible}

/* Inline folder-expansion chevron (inline-tree.js). Render it inline (V1's is
   absolute); rotate on expand; spinner while loading. Files get a spacer so
   names align. */
.files-row .files-name .files-row-chevron{position:static;transform:none;width:16px;height:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:3px}
.files-row .files-name .files-row-chevron:hover{background:rgba(255,255,255,.08)}
/* Glyph geometry stays V1's (files.css): the Adwaita pan arrow points up and
   is rotated 90° collapsed (→ right) / 180° expanded (→ down) at 16px. Only
   the container positioning above is adapted to V2's inline flex layout. */
.files-row .files-name .files-row-chevron svg{width:16px;height:16px;opacity:.6;transform:rotate(90deg);transition:transform .15s ease}
.files-row .files-name .files-row-chevron.expanded svg{transform:rotate(180deg)}
.files-name .files-row-chevron-spacer{width:16px;flex-shrink:0}
@keyframes spin{to{transform:rotate(360deg)}}
.files-row-spinner{display:block;width:10px;height:10px;border:1.5px solid var(--text-secondary);border-top-color:transparent;border-radius:50%;animation:spin .6s linear infinite}

/* ===================== BUTTON ADAPTERS =====================
   The snapshot styles V1's sidebar rows as <div>s; we use real <button>s for
   keyboard access, so strip the native chrome. */
.files-sidebar-item{border:0;background:transparent;font:inherit;width:100%;text-align:left;cursor:pointer}
.files-hamburger-btn{border:0}
.files-status-stats.error{color:var(--gp-error,#ff8c8c)}
#statusLeft.error{color:var(--gp-error,#ff8c8c)}
/* V1 row exit: fade + slide before the re-render removes the row (F3). */
.files-row-leaving{opacity:0!important;transform:translateX(30px);transition:opacity .18s ease,transform .18s ease;pointer-events:none}
.files-sidebar-item:focus-visible,.files-toolbar-btn:focus-visible,.files-row:focus-visible{outline:2px solid var(--gp-accent);outline-offset:-2px}
.files-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;flex:1;color:var(--text-secondary)}
.files-empty-icon{opacity:.7}

/* ===================== FEATURE DIALOGS (theme-token skin) =====================
   V2 has surfaces V1 never had (mounts, retention, delivery, grants…). They use
   native <dialog>; these rules dress them in the JessOS theme tokens. */
.dialog{
  width:min(440px,calc(100% - 32px));padding:0;color:var(--text-primary);
  background:var(--bg-window);border:1px solid var(--border-default);border-radius:12px;
  box-shadow:var(--shadow-lg);
}
.dialog::backdrop{background:rgba(0,0,0,.55)}
.dialog form,.dialog-body{padding:20px;display:flex;flex-direction:column;gap:12px}
.dialog h2{margin:0;font-size:17px;font-weight:600}
.dialog-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}
.dialog-section-title{margin:6px 0 0;font-size:12px;font-weight:600;color:var(--text-secondary)}
.eyebrow{margin:0 0 4px;font-size:11px;font-weight:700;letter-spacing:.1em;color:var(--text-muted)}
.dialog label{display:flex;flex-direction:column;gap:6px;font-size:12px;color:var(--text-secondary)}
.dialog input,.dialog select{height:34px;border:1px solid var(--input-border);border-radius:7px;padding:0 10px;font:inherit;font-size:13px;color:var(--input-text);background:var(--input-bg)}
.dialog input:focus,.dialog select:focus{outline:2px solid var(--focus-ring);outline-offset:-2px}
.dialog code,.link-secret{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}
.link-secret{display:block;padding:10px;border-radius:8px;background:var(--bg-view);border:1px solid var(--border-default);word-break:break-all}
.upload-picker{display:flex;flex-direction:column;gap:6px;font-size:12px;color:var(--text-secondary)}
progress{width:100%;height:8px}

.status-message{min-height:1.2em;margin:0;font-size:12px;color:var(--text-secondary)}
.status-message.error,.form-error{color:var(--gp-error);font-size:12px;margin:0}

.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:4px}
.button{border:1px solid transparent;border-radius:8px;padding:8px 14px;background:transparent;color:var(--text-primary);font:inherit;font-size:13px;font-weight:600;cursor:pointer}
.button:disabled,.disabled{opacity:.45;pointer-events:none}
.button-primary{background:var(--gp-accent);color:#fff;border-color:transparent}
.button-quiet{border-color:var(--border-default)}
.button-quiet:hover{background:var(--hover-overlay)}

.versions-list{display:flex;flex-direction:column;max-height:min(56vh,560px);overflow:auto;border-top:1px solid var(--border-default)}
.version-row{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:12px 0;border-bottom:1px solid var(--border-default);font-size:13px}
.version-row small{display:block;color:var(--text-secondary);font-size:11px}
.v2-link-actions{display:flex;gap:8px}

/* The users/grants dialogs reuse the V1 users.css .user-* grid; widen the shell. */
.v2-users-dialog{width:min(900px,calc(100% - 48px))}
.v2-users-dialog .user-list{max-height:min(58vh,620px);overflow:auto;margin-top:8px}

@media(max-width:800px){
  #window{top:52px;left:70px;right:14px;bottom:14px}
}

/* Dock Trash drop target (V1 dock.css rule removed with the recycle retirement). */
.dock-icon-pinned.drop-target {
  background: rgba(239, 83, 80, 0.25);
  border-radius: 8px;
  box-shadow: 0 0 0 2px rgba(239, 83, 80, 0.5);
}

/* Dock items carry no <button> UA chrome (V2 renders them as <button>s where
   V1 used <div>s, so the UA background/border leaked through). The bare button
   stays; the hover/active state is a separate rounded "backlight" drawn BEHIND
   the icon by a pseudo-element. Drawing it as its own layer (not the button's
   background) means it never inherits UA chrome. Sized to V1's plate — the 48px
   icon box at 8px radius (Jess tried a larger evenly-distributed halo and found
   it too big). */
#dock .dock-icon, #dock .dock-icon:hover, #dock .dock-icon.active {
  background: none; border: 0; box-shadow: none; appearance: none; -webkit-appearance: none; color: inherit;
}
#dock .dock-icon::before {
  content: ""; position: absolute; z-index: 0; inset: 0; /* V1 size: plate = the 48px icon box, not a larger halo (Jess: the extended one felt too big) */
  border-radius: 8px; background: transparent;
  transition: background 160ms ease; pointer-events: none;
}
#dock .dock-icon > img { position: relative; z-index: 1; } /* icon rides above its backlight */
#dock .dock-icon:hover::before { background: rgba(255, 255, 255, 0.1); }
#dock .dock-icon.active::before { background: rgba(255, 255, 255, 0.15); }
/* The tooltip and Trash size caption sit outside the plate; keep them on top. */
#dock .dock-icon-tooltip, #dock .dock-trash-size { z-index: 2; }
/* Trash size caption (spec 036 dock Trash, migration 0121): the approximate
   byte total of what the Trash holds, under the icon. Dock-native — tiny,
   dimmed, non-interactive, and absent entirely when the Trash is empty, so
   the dock stays a row of bare icons. */
#dock #dockTrash { position: relative; overflow: visible; }
#dock .dock-trash-size {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  margin-top: 2px; font: 9px/1 "Ubuntu", system-ui, sans-serif;
  letter-spacing: 0.02em; color: rgba(255, 255, 255, 0.55);
  white-space: nowrap; text-align: center; pointer-events: none;
  font-variant-numeric: tabular-nums;
}
#dock .dock-trash-size:empty { display: none; }
/* V1's dock.css has no disabled state; Empty Trash needs one so the item is
   shown-but-inert on an empty Trash rather than silently missing. */
.dock-context-menu-item-disabled { opacity: 0.45; cursor: default; }
.dock-context-menu-item-disabled:hover { background: transparent; }
#dock .dock-icon:focus { outline: none; }
#dock .dock-icon:focus-visible { outline: 2px solid rgba(255, 255, 255, 0.35); outline-offset: 2px; }
#dock .dock-icon-pinned.drop-target { background: rgba(239, 83, 80, 0.25); }

/* ===================== Users dock app (Spec 037) =====================
   V1's users.css styles the chrome; these are the V2-only touches: the
   6-column grid gains room for the row's Edit/Disable/Remove actions, the
   Invited lifecycle badge V1 never had, and the one-time credential
   handoff block. Scoped to the app's window body. */
#users-window-body { display: flex; flex-direction: column; overflow: auto; }
#users-window-body .user-list-header,
#users-window-body .user-row { grid-template-columns: 36px 1fr 120px 130px 90px 160px 110px; }
#users-window-body .users-last-activity { font-size: 12px; color: var(--text-muted); text-align: center; }
#users-window-body .user-actions { display: flex; gap: 4px; justify-content: flex-end; }
#users-window-body .role-badge.invited { background: rgba(230, 97, 0, 0.15); color: var(--accent-orange, #e66100); }
#users-window-body .users-app-error { padding: 8px 20px; color: var(--accent-red, #e01b24); font-size: 12px; }
#users-window-body .users-form-error { color: var(--accent-red, #e01b24); }
#users-window-body .users-edit-error { padding: 4px 20px; }
#users-window-body .users-inline-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
#users-window-body .users-grant-add { margin-top: 10px; }
#users-window-body .users-grant-capability { font-size: 11px; color: var(--text-muted); border: 1px solid var(--border-default, rgba(255,255,255,0.15)); border-radius: 10px; padding: 1px 8px; }
#users-window-body .users-credential-handoff { margin-top: 12px; border: 1px solid var(--accent-orange, #e66100); border-radius: 6px; padding: 12px; }
#users-window-body .users-credential-warning { font-size: 12px; color: var(--accent-orange, #e66100); margin: 0 0 8px; }
#users-window-body .users-credential-block { font-family: monospace; font-size: 12px; user-select: all; -webkit-user-select: all; white-space: pre-wrap; background: rgba(0, 0, 0, 0.25); border-radius: 4px; padding: 10px; margin: 0 0 8px; }

/* Users app: the caller's own row (0108 is_self) */
.users-you-chip{opacity:.55;font-weight:400;font-size:.85em}

/* ===================== Activity Logs L6 (spec 038): the evidence picker =====
   V1's logs.css has no selection styling; these V2-only touches keep the app
   consistent with the Files selection look — the desaturated-orange row fill
   plus an accent left border — and give the Evidence Report button V1's
   suggested-action (orange) state while download rows are selected. Scoped to
   the app's window body. */
#logs-window-body .logs-log-entry.selectable { cursor: pointer; user-select: none; }
#logs-window-body .logs-log-entry.selected,
#logs-window-body .logs-log-entry.selected:hover {
  background: rgba(212, 85, 0, 0.25); /* Files' .files-row.selected fill */
  box-shadow: inset 3px 0 0 var(--gp-accent, #f57c2a);
}
#logs-window-body .logs-filter-btn.primary {
  background: var(--btn-suggested-bg, #e66100);
  border-color: transparent;
  color: #fff;
}
#logs-window-body .logs-filter-btn.primary:hover { background: var(--btn-suggested-hover, #f57c2a); }
#logs-window-body .logs-filter-btn.primary:active { background: var(--btn-suggested-active, #d45500); }
/* Delivery-record lines inside the expanded .logs-file-list (issuance line,
   edge-delivery timeline, honest zero state). */
#logs-window-body .logs-record-line { padding: 3px 0 3px 24px; font-size: 12px; color: var(--text-secondary); }
#logs-window-body .logs-record-issuance { border-top: 1px solid var(--border-default, rgba(255, 255, 255, 0.12)); margin-top: 4px; padding-top: 7px; }
#logs-window-body .logs-record-delivery { color: var(--accent-green, #26a269); }
#logs-window-body .logs-record-empty { font-style: italic; color: var(--text-muted, var(--text-secondary)); }

/* ===================== Settings app (spec 039 T0/T1) =====================
   The chrome (sidebar-of-sections + cards) is V1's settings.css snapshot;
   these V2-only additions are the window-body seam plus the Usage card's
   stacked bar and bucket rows, scoped to the app's window body. */
#settings-window-body { flex: 1; background: var(--bg-view); display: flex; flex-direction: column; min-height: 0; position: relative; overflow: hidden; }
#settings-window-body[hidden] { display: none; }
#settings-window-body .card-header .form-hint { float: right; font-weight: 400; }
#settings-window-body .v2-settings-error { color: var(--accent-red, #e01b24); }
#settings-window-body .v2-usage-bar { display: flex; height: 10px; border-radius: 5px; overflow: hidden; background: var(--gp-gray-600, rgba(255, 255, 255, 0.08)); margin-bottom: 16px; }
#settings-window-body .v2-usage-segment { min-width: 2px; }
#settings-window-body .v2-usage-row { display: grid; grid-template-columns: 160px 90px 1fr; align-items: baseline; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border-default, rgba(255, 255, 255, 0.08)); }
#settings-window-body .v2-usage-row:last-of-type { border-bottom: none; }
#settings-window-body .v2-usage-total .breakdown-type,
#settings-window-body .v2-usage-total .breakdown-size { font-weight: 600; }
#settings-window-body .v2-usage-active { background: var(--gp-accent, #f57c2a); }
#settings-window-body .v2-usage-versions { background: var(--accent-purple, #9141ac); }
#settings-window-body .v2-usage-trash { background: var(--text-muted, #9a9996); }
#settings-window-body .v2-usage-delivery { background: var(--accent-blue, #3584e4); }

/* General → Wallpaper picker (synced `wallpaper` pref; spec 039 IA 2026-08-24) */
#settings-window-body .v2-wallpaper-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; margin-bottom: 10px; }
#settings-window-body .v2-wallpaper-choice { padding: 0; border: 2px solid transparent; border-radius: 8px; overflow: hidden; cursor: pointer; background: var(--gp-gray-600, rgba(255, 255, 255, 0.08)); line-height: 0; transition: border-color 0.12s ease; }
#settings-window-body .v2-wallpaper-choice img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block; }
#settings-window-body .v2-wallpaper-choice:hover { border-color: var(--border-strong, rgba(255, 255, 255, 0.3)); }
#settings-window-body .v2-wallpaper-choice.selected { border-color: var(--gp-accent, #f57c2a); }
#settings-window-body .v2-wallpaper-choice:focus-visible { outline: 2px solid var(--gp-accent, #f57c2a); outline-offset: 2px; }

/* Account → Active Sessions (spec 039 T3) */
#settings-window-body .v2-session-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-default, rgba(255, 255, 255, 0.08)); }
#settings-window-body .v2-session-row:last-of-type { border-bottom: none; }
#settings-window-body .v2-session-facts { display: flex; flex-direction: column; gap: 2px; }
#settings-window-body .v2-session-title { font-weight: 600; }
#settings-window-body .v2-session-badge { flex: none; font-size: 12px; font-weight: 600; padding: 2px 10px; border-radius: 99px; background: var(--gp-accent, #f57c2a); color: var(--gp-gray-900, #1d1d1d); }
#settings-window-body .v2-session-current .v2-session-title { color: var(--gp-accent, #f57c2a); }

/* =====================================================================
   Workspace switcher (spec 040 §8) — Ubuntu/GNOME-style topbar dropdown.
   Scoped to .workspace-switcher-*; matches the dark topbar snapshot.
   ===================================================================== */
.workspace-switcher { position: relative; }
.workspace-switcher-button {
  display: inline-flex; align-items: center; gap: 6px;
  background: transparent; border: none; color: inherit; font: inherit;
  text-shadow: inherit; padding: 4px 8px; margin: -4px -8px; border-radius: 6px;
  cursor: pointer;
}
.workspace-switcher-button:hover,
.workspace-switcher-button[aria-expanded="true"] { background: rgba(255, 255, 255, 0.1); }
.workspace-switcher-button:focus-visible { outline: 2px solid var(--gp-accent, #f57c2a); outline-offset: 1px; }
.workspace-switcher-chevron { opacity: 0.7; flex: none; }
.workspace-switcher-menu {
  position: absolute; top: calc(100% + 8px); left: 26px; min-width: 240px; max-width: 340px;
  background: rgba(42, 42, 42, 0.98);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.35);
  padding: 6px; z-index: 400;
  display: flex; flex-direction: column;
}
.workspace-switcher-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: transparent; border: none; color: #f1f1f1; font: inherit; font-size: 13px;
  text-align: left; padding: 8px 10px; border-radius: 8px; cursor: pointer;
}
.workspace-switcher-item:hover { background: rgba(255, 255, 255, 0.1); }
.workspace-switcher-item:focus-visible { outline: 2px solid var(--gp-accent, #f57c2a); outline-offset: -2px; }
.workspace-switcher-item.current .workspace-switcher-name { font-weight: 600; }
.workspace-switcher-item.danger:hover { background: rgba(224, 27, 36, 0.25); }
.workspace-switcher-checkslot { flex: none; width: 16px; display: inline-flex; align-items: center; justify-content: center; }
.workspace-switcher-check { color: var(--gp-accent, #f57c2a); }
.workspace-switcher-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.workspace-switcher-separator { height: 1px; margin: 6px 8px; background: rgba(255, 255, 255, 0.12); }

/* Create OneTime Link: archive password input + Generate side-by-side. */
.share-archive-row{display:flex;gap:8px;align-items:center}
.share-archive-row input{flex:1;min-width:0}

/* Link Created dialog (V1 parity, refined): link + inline Copy on one row;
   each password in its own amber-outlined row with its own Copy — copied
   separately by design so link and password travel over different channels. */
.link-secret-row{display:grid;grid-template-columns:1fr 72px;gap:8px;align-items:center;margin-top:8px}
.link-secret-row .button{width:100%}
.link-secret-row .link-secret{min-width:0;overflow-wrap:anywhere}
.link-password-box{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:8px 12px;border:1px solid rgba(204,160,0,.55);border-radius:8px;background:rgba(204,160,0,.08);font-size:13px;min-width:0}
.link-password-box em{color:var(--text-secondary);font-style:normal;font-size:12px}
#link-expiry-line{margin-top:10px}

/* Access-password field masked via CSS, NOT type=password: Safari treats any
   password-type input in a submitting form as a site credential and offers to
   save it on every link creation. A text input with -webkit-text-security
   masks identically in Safari/Chrome and never trips the credential heuristic.
   The Show/Hide toggle flips .revealed. */
.masked-secret{-webkit-text-security:disc}
.masked-secret.revealed{-webkit-text-security:none}

/* ===================== OneTime Links dock app (Spec 041 Slice 6) =========
   V1 share-links visual language: header + search, All/Active/Expired tabs,
   icon-fronted rows with creator/evidence lines and icon action buttons. */
/* OneTime Links — Nautilus-style column list (2026-09-07). Header and rows
   share one grid so cells line up: status · name · created · expires ·
   last download · protection flags · menu. */
#links-app-window-body { display: flex; flex-direction: column; overflow: hidden; }
.links-app { display: flex; flex-direction: column; flex: 1; min-height: 0; }
/* Same height as the Files toolbar: 8px padding around 32px controls. */
.links-app-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 12px; background: var(--toolbar-bg); border-bottom: 1px solid var(--border-default); flex-shrink: 0; }
.links-app-switcher { display: inline-flex; height: 32px; box-sizing: border-box; background: var(--hover-overlay); border-radius: 8px; padding: 3px; }
.links-app-tab { padding: 0 14px; background: none; border: none; border-radius: 6px; color: var(--text-secondary); font: inherit; font-size: 13px; font-weight: 500; }
.links-app-tab:hover { color: var(--text-primary); }
.links-app-tab.active { background: var(--active-overlay, rgba(255,255,255,.12)); color: var(--text-primary); }
.links-app-search { height: 32px; box-sizing: border-box; padding: 0 12px; background: var(--input-bg); border: 1px solid var(--border-default); border-radius: 8px; color: var(--text-primary); font: inherit; font-size: 13px; width: 200px; }
.links-app-search:focus { outline: none; border-color: var(--accent-orange, #e66100); }
.links-app-message { margin: 0; padding: 4px 16px; }
.links-app-message:empty { display: none; }
.links-app-header, .links-app-row-main { display: grid; grid-template-columns: 16px 76px 40px minmax(0, 1fr) 122px 86px minmax(200px, .9fr) 32px; gap: 8px; align-items: center; }
.links-app-chevron { position: static; transform: none; }
.links-app-chevron svg { opacity: .6; }
.links-app-header { padding: 8px 16px; }
.links-app-scroll { flex: 1; min-height: 0; overflow-y: auto; }
.links-app-empty { color: var(--text-secondary); font-size: 13px; margin: 0; padding: 28px 16px; text-align: center; }
.links-app-row { border-bottom: 1px solid var(--row-border); }
.links-app-row-main { padding: 6px 16px; min-height: 40px; font-size: 13px; text-shadow: var(--text-shadow); }
.links-app-row-main:hover { background: var(--row-bg-hover, var(--list-hover)); }
.links-app-row.open > .links-app-row-main { background: var(--row-bg-hover, var(--list-hover)); }
.links-app-target { color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.links-app-cell { color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.links-app-flags { display: flex; gap: 4px; color: var(--text-secondary); justify-content: flex-start; min-height: 14px; }
.links-app-flags span { display: inline-flex; }
.links-app-state { border: none; border-radius: 999px; padding: 3px 0; width: 68px; font: inherit; font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; text-align: center; }
.links-app-state.active { background: rgba(46,160,67,.2); color: #57d36a; }
.links-app-state.active:hover { background: rgba(224,27,36,.2); color: #ff6b6b; }
.links-app-state.expired { background: rgba(255,255,255,.08); color: var(--text-secondary); }
.links-app-state.revoked { background: rgba(224,27,36,.15); color: #ff6b6b; }
.links-app-state.expired:hover, .links-app-state.revoked:hover { background: rgba(46,160,67,.2); color: #57d36a; }
.links-app-more { width: 28px; height: 28px; border: none; border-radius: 50%; background: transparent; color: var(--text-secondary); display: flex; align-items: center; justify-content: center; justify-self: end; }
.links-app-more:hover { background: var(--hover-overlay); color: var(--text-primary); }
.links-app-menu { min-width: 200px; }
.links-app-activity { padding: 6px 16px 10px 124px; display: flex; flex-direction: column; gap: 4px; background: rgba(0,0,0,.12); }
.links-app-activity .links-app-empty { padding: 4px 0; text-align: left; font-size: 12px; }
.links-app-event { display: grid; grid-template-columns: 120px 1fr auto; gap: 2px 10px; font-size: 12px; color: var(--text-secondary); padding: 3px 0; }
.links-app-event-where { grid-column: 2 / 4; display: flex; align-items: center; gap: 4px; margin-left: -20px; font-variant-numeric: tabular-nums; color: var(--text-muted, var(--text-secondary)); }
.links-app-event-more { display: inline-flex; align-items: center; border: none; background: none; padding: 0; width: 16px; height: 16px; color: var(--text-secondary); border-radius: 3px; }
.links-app-event-more:hover { color: var(--text-primary); background: var(--hover-overlay); }
.links-app-event-more svg { width: 14px; height: 14px; opacity: .6; transform: rotate(90deg); transition: transform 150ms ease; }
.links-app-event.open .links-app-event-more svg { transform: rotate(180deg); }
.links-app-event-details { display: none; grid-column: 2 / 4; margin: 4px 0 6px; padding: 8px 12px; border: 1px solid var(--border-default); border-radius: 6px; background: rgba(0,0,0,.15); grid-template-columns: 130px 1fr; gap: 3px 12px; font-size: 12px; }
.links-app-event.open .links-app-event-details { display: grid; }
.links-app-event-details dt { color: var(--text-secondary); margin: 0; }
.links-app-event-details dd { margin: 0; color: var(--text-primary); overflow-wrap: anywhere; }
.links-app-event-details dd.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; }
.links-app-event-what { color: var(--text-primary); }

/* Settings preference rows (Adwaita AdwActionRow discipline): a card body is
   a list of rows — title + subtitle left, ONE control cluster right, hairline
   separators — so every section reads the same way. Stacked rows put a wide
   control (a picker grid) under the title. */
.v2-pref-list { padding-top: 0; padding-bottom: 0; }
.v2-pref-row { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 14px 0; border-bottom: 1px solid rgba(255,255,255,.08); }
.v2-pref-row:last-child { border-bottom: none; }
.v2-pref-row-stacked { flex-direction: column; align-items: stretch; gap: 12px; }
.v2-pref-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.v2-pref-title { font-size: 14px; font-weight: 500; color: var(--text-primary); }
.v2-pref-subtitle { font-size: 12px; color: var(--text-secondary); }
.v2-pref-control { display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex-shrink: 0; min-width: 320px; max-width: 460px; }
.v2-pref-control .form-input, .v2-pref-control .form-select { width: 100%; min-width: 0; }
.v2-pref-control.color-input input[type="color"] { width: 36px; height: 36px; flex-shrink: 0; }
.v2-pref-control.color-input .form-input { width: 110px; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.v2-pref-control.logo-upload { min-width: 0; }
.v2-pref-control.logo-upload .logo-preview { width: 48px; height: 48px; border-radius: 50%; background: #0006; }
.v2-pref-control.logo-upload .logo-preview img { width: 40px; height: 40px; object-fit: contain; }
.v2-pref-control.logo-upload .logo-actions { flex-direction: row; }
.v2-pref-row-disabled .v2-pref-text { opacity: .6; }
.v2-pro-tag { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px; font-size: 10px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: #e8c04a; border: 1px solid rgba(204,160,0,.55); background: rgba(204,160,0,.12); vertical-align: middle; }
.section-actions #brand-message { margin-right: auto; }

/* Settings → Share page live preview (spec 041 Slice 8): the real login-card
   language on the chosen wallpaper, scaled down to sit inside a settings card. */
.v2-brand-preview { padding: 0 18px 18px; border-radius: 10px; background: #2c001e center/cover no-repeat; display: flex; flex-direction: column; align-items: center; gap: 14px; overflow: hidden; }
.v2-brand-preview-topbar { align-self: stretch; margin: 0 -18px; height: 26px; display: flex; align-items: center; gap: 8px; padding: 0 12px; background: rgba(0,0,0,.72); color: #fff; font-size: 12px; font-weight: 500; }
.v2-brand-preview-topbar img { width: 14px; height: 14px; }
.v2-brand-preview .v2-login-card { max-width: 340px; transform: scale(.92); transform-origin: top center; pointer-events: none; }
.v2-brand-preview .v2-login-button { min-width: 110px; height: 30px; font-size: 12px; }

/* The path bar's height was content-driven: a crumb with the 16px folder icon
   stood taller than the 12px Home glyph alone, so the bar shrank at the root
   (visible on the share page, where root is Home only). Pin the crumb height
   to the icon-bearing case so the bar never moves. */
.files-breadcrumb-item { min-height: 22px; }
.files-path-bar { min-height: 30px; }

/* Duration prompt (Restore / Change expiry): GTK spin button + unit select. */
.files-modal-duration { display: flex; gap: 8px; align-items: stretch; }
.files-modal-spin { position: relative; width: 76px; flex: none; }
.files-modal-spin .files-modal-input { padding-right: 34px; -moz-appearance: textfield; appearance: textfield; font-variant-numeric: tabular-nums; }
.files-modal-spin .files-modal-input::-webkit-outer-spin-button, .files-modal-spin .files-modal-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.files-modal-spin-buttons { position: absolute; top: 1px; right: 1px; bottom: 1px; width: 28px; display: flex; flex-direction: column; border-left: 1px solid var(--input-border); border-radius: 0 5px 5px 0; overflow: hidden; }
.files-modal-spin-btn { flex: 1; border: none; background: var(--btn-bg, rgba(255,255,255,.06)); color: var(--text-secondary); padding: 0; display: flex; align-items: center; justify-content: center; }
.files-modal-spin-btn + .files-modal-spin-btn { border-top: 1px solid var(--input-border); }
.files-modal-spin-btn:hover { background: var(--btn-bg-hover, rgba(255,255,255,.12)); color: var(--text-primary); }
.files-modal-spin-btn:active { background: var(--btn-bg-active, rgba(0,0,0,.2)); }
.files-modal-select { width: 120px; flex: none; padding-right: 28px; appearance: none; -webkit-appearance: none; background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10"><path d="m2 3.5 3 3 3-3" fill="none" stroke="%23cfcfcf" stroke-width="1.5"/></svg>'); background-repeat: no-repeat; background-position: right 10px center; }
.files-modal-select option { background: var(--menu-bg, #2b2b2b); color: var(--text-primary); }
