Spaces:
Running
Running
Download frontend/src/styles.css from devaanand/ccr-platform: direct link, hf CLI and curl.
- Browser
- Download file 42.9 kB
-
https://huggingface.co/spaces/devaanand/ccr-platform/resolve/main/frontend/src/styles.css
- Command line
-
hf download hf://spaces/devaanand/ccr-platform/frontend/src/styles.css
-
curl -L -o styles.css https://huggingface.co/spaces/devaanand/ccr-platform/resolve/main/frontend/src/styles.css
42.9 kB
| :root { | |
| /* CAML (Culture & Morality Lab) palette, from the CCR logo: near-black | |
| strokes + teal similarity dots. --brand is a darkened logo teal so text | |
| and buttons keep AA contrast on white; --accent is the logo teal itself, | |
| used for non-text fills (bars, dots, highlights). */ | |
| --brand-ink: #151515; | |
| --brand: #26736f; | |
| --brand-dark: #1d5a57; | |
| --accent: #339b98; | |
| --ink: #1d2129; | |
| --muted: #667085; | |
| --line: #e5e7eb; | |
| --bg: #f7f7f8; | |
| /* the sidebar rail: a shade under the canvas, the way Claude and ChatGPT | |
| separate navigation from content without a border doing the work */ | |
| --rail: #f1f1f3; | |
| --card: #ffffff; | |
| --ok: #157f3d; | |
| --err: #b42318; | |
| --accent-soft: #e7f3f2; | |
| --control-height: 40px; | |
| /* modern surface language: one radius pair, layered shadows, one focus ring */ | |
| --radius: 12px; | |
| --radius-sm: 9px; | |
| --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06); | |
| --shadow-md: 0 2px 6px rgba(16, 24, 40, 0.05), 0 12px 24px -16px rgba(16, 24, 40, 0.14); | |
| --shadow-lg: 0 24px 60px -12px rgba(16, 24, 40, 0.26); | |
| --ring: 0 0 0 3px rgba(51, 155, 152, 0.18); | |
| } | |
| * { box-sizing: border-box; } | |
| body { | |
| margin: 0; | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif; | |
| color: var(--ink); | |
| background: var(--bg); | |
| font-size: 14.5px; | |
| line-height: 1.5; | |
| } | |
| /* Grayscale antialiasing only on high-DPI screens, where it looks cleaner. | |
| On 1x displays it kills subpixel rendering and text goes fuzzy. */ | |
| @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) { | |
| body { -webkit-font-smoothing: antialiased; } | |
| } | |
| /* thin, unobtrusive scrollbars everywhere */ | |
| * { scrollbar-width: thin; scrollbar-color: #c3c9d1 transparent; } | |
| *::-webkit-scrollbar { width: 8px; height: 8px; } | |
| *::-webkit-scrollbar-thumb { background: #c3c9d1; border-radius: 999px; } | |
| *::-webkit-scrollbar-track { background: transparent; } | |
| .app { display: flex; flex-direction: column; min-height: 100vh; } | |
| /* The dashboard is an app shell, not a document: it fills the viewport exactly | |
| and the two panes scroll inside it, so the sidebar's account row and the | |
| "New project" button stay put instead of drifting to the bottom of a long | |
| page. Below 820px the sidebar is a drawer and the page scrolls normally, so | |
| this must not apply there. */ | |
| @media (min-width: 821px) { | |
| .app-dashboard { height: 100vh; overflow: hidden; } | |
| } | |
| a { color: var(--brand); } | |
| /* ---------- top line (landing page and /admin only) ---------- | |
| Every screen used to wear a dark banner with the product's full name in it. | |
| The dashboard now has no top chrome at all - its sidebar is the chrome, as | |
| in Claude and ChatGPT - and the two views with no sidebar get this instead: | |
| light, quiet, and no tagline. */ | |
| .topline { | |
| position: sticky; top: 0; z-index: 30; | |
| display: flex; align-items: center; gap: 16px; | |
| padding: 12px 24px; | |
| background: rgba(247, 247, 248, 0.82); | |
| backdrop-filter: saturate(180%) blur(10px); | |
| -webkit-backdrop-filter: saturate(180%) blur(10px); | |
| border-bottom: 1px solid var(--line); | |
| } | |
| .topline .brand { display: inline-flex; align-items: center; text-decoration: none; } | |
| .brand-logo { height: 26px; width: auto; display: block; } | |
| .topline-nav { | |
| margin-left: auto; | |
| display: flex; align-items: center; gap: 16px; flex-wrap: wrap; | |
| } | |
| .top-link { | |
| background: none; border: 0; padding: 0; | |
| font: inherit; font-size: 13.5px; color: var(--muted); | |
| cursor: pointer; text-decoration: none; transition: color 0.15s ease; | |
| } | |
| .top-link:hover { color: var(--ink); } | |
| .top-name { font-size: 13px; color: var(--muted); } | |
| .top-btn { | |
| background: var(--brand); color: #fff; border: 0; | |
| padding: 8px 15px; border-radius: 9px; | |
| font: inherit; font-size: 13px; font-weight: 600; line-height: 1; | |
| cursor: pointer; text-decoration: none; | |
| transition: background-color 0.15s ease; | |
| } | |
| .top-btn:hover { background: var(--brand-dark); } | |
| /* A quiet square button for icons: the sidebar's collapse control and the one | |
| that brings it back. */ | |
| .icon-btn { | |
| display: inline-flex; align-items: center; justify-content: center; | |
| width: 30px; height: 30px; padding: 0; flex-shrink: 0; | |
| border: 0; border-radius: 8px; background: none; | |
| color: var(--muted); cursor: pointer; | |
| transition: background-color 0.15s ease, color 0.15s ease; | |
| } | |
| .icon-btn:hover { background: rgba(16, 24, 40, 0.07); color: var(--ink); } | |
| .layout { display: flex; flex: 1; min-width: 0; min-height: 0; } | |
| /* ---------- collapsible sidebar ---------- | |
| Closed, the sidebar slides out of the row on its own negative margin rather | |
| than animating to width 0: it keeps its 250px, so nothing inside reflows on | |
| the way out, and off-screen-left content adds no page scroll. */ | |
| .sidebar { transition: margin-left 0.18s ease; } | |
| .layout.sidebar-closed .sidebar { margin-left: -250px; } | |
| .sidebar-toggle { | |
| flex: 0 0 auto; order: -1; | |
| display: inline-flex; align-items: center; justify-content: center; | |
| width: 32px; height: 32px; padding: 0; | |
| background: rgba(255, 255, 255, 0.1); color: #fff; | |
| border: 1px solid rgba(255, 255, 255, 0.28); border-radius: 8px; | |
| cursor: pointer; transition: background-color 0.15s ease; | |
| } | |
| .sidebar-toggle:hover { background: rgba(255, 255, 255, 0.22); } | |
| /* The backdrop exists only under 820px, where the sidebar is a drawer. */ | |
| .sidebar-backdrop { display: none; } | |
| /* ---------- sidebar ---------- */ | |
| .sidebar { | |
| width: 250px; | |
| background: var(--rail); | |
| border-right: 1px solid var(--line); | |
| padding: 10px 12px 12px; | |
| flex-shrink: 0; | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 0; | |
| } | |
| .sidebar-head { | |
| display: flex; align-items: center; justify-content: space-between; | |
| gap: 8px; padding: 2px 2px 8px; | |
| } | |
| .brand-mini { | |
| display: inline-flex; align-items: center; | |
| border: 0; background: none; padding: 2px; cursor: pointer; border-radius: 8px; | |
| } | |
| .brand-mini img, .brand-mini-img { height: 22px; width: auto; display: block; } | |
| .brand-mini:hover { background: rgba(16, 24, 40, 0.06); } | |
| /* ---------- account chip + menu (sidebar foot) ---------- | |
| Everything the banner used to carry now hangs off one chip, ChatGPT style: | |
| avatar, who you are, what kind of account it is, and a menu that opens | |
| upward with the guides, the lab-only pages, admin, and the way in or out. */ | |
| .sidebar-foot { | |
| margin-top: 10px; padding-top: 10px; | |
| border-top: 1px solid var(--line); | |
| } | |
| .account { position: relative; } | |
| .account-chip { | |
| display: flex; align-items: center; gap: 10px; width: 100%; | |
| padding: 7px 8px; border: 0; border-radius: 10px; | |
| background: none; font: inherit; text-align: left; cursor: pointer; | |
| transition: background-color 0.15s ease; | |
| } | |
| .account-chip:hover { background: rgba(16, 24, 40, 0.06); } | |
| .account-chip-id { min-width: 0; display: flex; flex-direction: column; } | |
| .account-chip-id b, | |
| .account-chip-sub { | |
| min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; | |
| } | |
| .account-chip-id b { font-size: 13px; font-weight: 600; } | |
| .account-chip-sub { font-size: 11.5px; color: var(--muted); } | |
| .account-chip-caret { margin-left: auto; flex-shrink: 0; color: var(--muted); } | |
| .avatar { | |
| flex-shrink: 0; | |
| display: inline-flex; align-items: center; justify-content: center; | |
| width: 28px; height: 28px; border-radius: 50%; | |
| background: var(--brand); color: #fff; | |
| font-size: 11.5px; font-weight: 700; letter-spacing: 0.3px; | |
| } | |
| .avatar-anon { background: #c7ccd3; color: #fff; font-weight: 600; } | |
| .account-menu { | |
| position: absolute; bottom: calc(100% + 8px); left: 0; right: 0; z-index: 50; | |
| background: var(--card); border: 1px solid var(--line); | |
| border-radius: var(--radius); box-shadow: var(--shadow-lg); | |
| padding: 6px; animation: float-in 0.14s ease-out; | |
| } | |
| .account-menu-head { | |
| display: flex; align-items: center; gap: 10px; | |
| padding: 8px 8px 10px; margin-bottom: 4px; | |
| border-bottom: 1px solid var(--line); | |
| } | |
| .account-menu-id { min-width: 0; display: flex; flex-direction: column; } | |
| .account-menu-id b { font-size: 13px; } | |
| .account-menu-id > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } | |
| .account-menu-items { display: flex; flex-direction: column; } | |
| .account-menu-end { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line); } | |
| .menu-item { | |
| display: flex; align-items: center; gap: 10px; width: 100%; | |
| padding: 8px 8px; border: 0; border-radius: 8px; | |
| background: none; color: var(--ink); font: inherit; font-size: 13px; | |
| text-align: left; text-decoration: none; cursor: pointer; | |
| white-space: nowrap; /* the base button rule, restated for the <a> items */ | |
| } | |
| .menu-item:hover { background: var(--bg); } | |
| .menu-icon { flex-shrink: 0; color: var(--muted); } | |
| .menu-item:hover .menu-icon { color: var(--brand); } | |
| .sidebar h2 { | |
| font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.7px; | |
| color: var(--muted); margin: 0 0 10px 4px; | |
| display: flex; align-items: center; gap: 8px; | |
| } | |
| .sidebar h2 .count { | |
| background: var(--bg); border: 1px solid var(--line); border-radius: 999px; | |
| padding: 0 8px; font-size: 10.5px; letter-spacing: 0; color: var(--muted); | |
| } | |
| .sidebar-filter { | |
| width: 100%; padding: 7px 10px; margin-bottom: 10px; | |
| /* white on the tinted rail, so the field reads as a field */ | |
| border: 1px solid var(--line); border-radius: var(--radius-sm); font: inherit; font-size: 13px; | |
| background: #fff; color: var(--ink); | |
| } | |
| .sidebar-filter:focus { outline: none; border-color: var(--brand); } | |
| .project-list { | |
| flex: 1 1 auto; | |
| min-height: 0; | |
| overflow-y: auto; | |
| margin: 0 -4px; | |
| padding: 0 4px 4px; | |
| } | |
| .group-label { | |
| font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.6px; | |
| color: var(--muted); margin: 10px 4px 5px; | |
| } | |
| div:first-child > .group-label { margin-top: 2px; } | |
| .project-item { | |
| display: block; width: 100%; text-align: left; | |
| padding: 9px 12px; margin-bottom: 5px; | |
| border: 1px solid transparent; border-radius: var(--radius-sm); | |
| background: none; cursor: pointer; font: inherit; color: var(--ink); | |
| } | |
| .project-item:hover { background: rgba(16, 24, 40, 0.05); } | |
| .project-item.active { background: var(--card); border-color: var(--brand); font-weight: 600; } | |
| .project-item .project-name { | |
| display: block; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .project-item .date { display: block; font-size: 11.5px; color: var(--muted); font-weight: 400; } | |
| .project-create { | |
| margin-top: 12px; | |
| padding-top: 12px; | |
| border-top: 1px solid var(--line); | |
| } | |
| .project-create > button { width: 100%; } | |
| /* ---------- main ---------- */ | |
| /* 7px, not a round number: it puts the project name on the same line as the | |
| logo across the divider (measured, 5px out at 12px). */ | |
| .main { flex: 1; padding: 7px 28px 28px; overflow-y: auto; min-width: 0; } | |
| /* Rendered only while the sidebar is collapsed: holding the row open the rest | |
| of the time left an empty strip above the project name, and set the heading | |
| out of line with the logo across the divider. */ | |
| .main-toolbar { | |
| display: flex; align-items: center; gap: 10px; | |
| height: 32px; margin-bottom: 6px; | |
| } | |
| .card { | |
| background: var(--card); border: 1px solid var(--line); | |
| border-radius: var(--radius); padding: 18px 20px; margin-bottom: 16px; | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .card h3 { margin: 0 0 4px; font-size: 15px; } | |
| .card .hint { color: var(--muted); font-size: 12.5px; margin: 0 0 12px; } | |
| .step-badge { | |
| display: inline-flex; align-items: center; justify-content: center; | |
| width: 21px; height: 21px; border-radius: 50%; | |
| background: var(--brand); color: #fff; font-size: 12px; font-weight: 700; | |
| margin-right: 8px; vertical-align: -3px; | |
| } | |
| /* ---------- controls ---------- */ | |
| button { white-space: nowrap; } | |
| button.primary { | |
| background: var(--brand); color: #fff; border: none; | |
| min-height: var(--control-height); | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 0 18px; border-radius: var(--radius-sm); font: inherit; font-weight: 600; cursor: pointer; | |
| line-height: 1.2; | |
| transition: background-color 0.15s ease; | |
| } | |
| button.primary:hover { background: var(--brand-dark); } | |
| button.primary:active { transform: translateY(1px); } | |
| button.primary:disabled { background: #c9ccd1; cursor: not-allowed; transform: none; } | |
| a.google-btn { | |
| background: var(--brand); color: #fff; border: none; | |
| min-height: var(--control-height); | |
| display: flex; align-items: center; justify-content: center; | |
| padding: 0 18px; border-radius: var(--radius-sm); font: inherit; font-weight: 600; | |
| cursor: pointer; line-height: 1.2; text-decoration: none; width: 100%; | |
| box-sizing: border-box; | |
| } | |
| a.google-btn:hover { background: var(--brand-dark); } | |
| button.ghost, a.ghost { | |
| background: none; border: 1px solid var(--line); color: var(--ink); | |
| min-height: var(--control-height); | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 0 14px; border-radius: var(--radius-sm); font: inherit; cursor: pointer; | |
| line-height: 1.2; text-decoration: none; | |
| transition: border-color 0.15s ease, color 0.15s ease; | |
| } | |
| button.ghost:hover, a.ghost:hover { | |
| border-color: var(--brand); color: var(--brand); background: var(--accent-soft); | |
| } | |
| button.ghost:active, a.ghost:active { transform: translateY(1px); } | |
| button.linkish { | |
| background: none; border: none; color: var(--brand); | |
| font: inherit; cursor: pointer; padding: 0; text-decoration: underline; | |
| } | |
| input[type="text"], input[type="email"], input[type="password"], textarea, select { | |
| width: 100%; padding: 8px 10px; border: 1px solid var(--line); | |
| border-radius: var(--radius-sm); font: inherit; background: #fff; color: var(--ink); | |
| } | |
| input[type="text"], input[type="email"], input[type="password"], select { height: var(--control-height); } | |
| input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus, | |
| textarea:focus, select:focus { | |
| outline: none; border-color: var(--accent); box-shadow: var(--ring); | |
| } | |
| button:focus-visible, | |
| input:focus-visible, | |
| textarea:focus-visible, | |
| select:focus-visible { | |
| outline: 2px solid rgba(51, 155, 152, 0.5); | |
| outline-offset: 2px; | |
| } | |
| /* File input: block-level with breathing room under its label, and a styled | |
| picker button so it matches the rest of the controls. */ | |
| input[type="file"] { | |
| display: block; max-width: 100%; margin-top: 6px; font-size: 13px; color: var(--muted); | |
| } | |
| input[type="file"]::file-selector-button { | |
| background: #fff; border: 1px solid var(--line); color: var(--ink); | |
| padding: 7px 14px; border-radius: var(--radius-sm); font: inherit; font-size: 13px; | |
| cursor: pointer; margin-right: 10px; | |
| } | |
| input[type="file"]::file-selector-button:hover { | |
| border-color: var(--brand); color: var(--brand); | |
| } | |
| /* Buttons inside a row of labeled fields align to the controls' baseline | |
| instead of stretching to the row's full height. */ | |
| .row > button { align-self: flex-end; margin-bottom: 1px; } | |
| textarea { resize: vertical; } | |
| label.field { display: block; margin-bottom: 10px; font-size: 13px; font-weight: 600; } | |
| label.field > * { margin-top: 4px; font-weight: 400; } | |
| .field-hint { margin-top: 0; font-weight: 400; color: var(--muted); font-size: 12px; } | |
| .row { display: flex; gap: 14px; flex-wrap: wrap; } | |
| .row > * { min-width: 0; } | |
| .row > .grow { flex: 1; min-width: min(220px, 100%); } | |
| .language-control { min-width: 170px; } | |
| .model-control { min-width: 260px; } | |
| .run-settings { | |
| display: grid; | |
| grid-template-columns: minmax(160px, 230px) minmax(320px, 720px) max-content; | |
| justify-content: start; | |
| gap: 14px; | |
| align-items: end; | |
| } | |
| .run-settings .field { margin-bottom: 0; } | |
| .run-button { | |
| min-width: 180px; | |
| height: var(--control-height); | |
| } | |
| .construct-row { | |
| display: grid; | |
| grid-template-columns: minmax(320px, 1120px) max-content; | |
| justify-content: start; | |
| align-items: end; | |
| gap: 14px; | |
| } | |
| .results-toolbar { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 14px; | |
| margin-bottom: 14px; | |
| flex-wrap: wrap; | |
| } | |
| .result-actions { justify-content: flex-end; } | |
| .result-actions a { display: inline-flex; text-decoration: none; } | |
| /* ---------- misc ---------- */ | |
| .pill { | |
| display: inline-flex; align-items: center; gap: 6px; | |
| padding: 2px 10px; border-radius: 999px; | |
| font-size: 11.5px; font-weight: 600; | |
| } | |
| .pill::before { | |
| content: ""; width: 6px; height: 6px; border-radius: 50%; | |
| background: currentColor; opacity: 0.75; | |
| } | |
| .pill.running::before { animation: pill-pulse 1.2s ease-in-out infinite; } | |
| @keyframes pill-pulse { | |
| 50% { opacity: 0.2; } | |
| } | |
| .pill.completed { background: #e6f4ea; color: var(--ok); } | |
| .pill.running { background: #fff3e0; color: #b45309; } | |
| .pill.queued { background: #eef2f7; color: var(--muted); } | |
| .pill.failed { background: #fdecea; color: var(--err); } | |
| .progress-track { background: var(--line); border-radius: 999px; height: 7px; overflow: hidden; } | |
| .progress-fill { | |
| background: linear-gradient(90deg, var(--brand), var(--accent)); | |
| height: 100%; transition: width 0.4s ease; border-radius: 999px; | |
| } | |
| .warnings { | |
| background: #fff8e6; border: 1px solid #f2dfa8; color: #7a5b00; | |
| border-radius: var(--radius-sm); padding: 10px 14px; | |
| } | |
| .error-banner { | |
| background: #fdecea; color: var(--err); border: 1px solid #f5c6c0; | |
| padding: 10px 14px; border-radius: var(--radius-sm); margin-bottom: 14px; font-size: 13px; | |
| } | |
| .table-wrap { width: 100%; overflow-x: auto; } | |
| table.docs { width: 100%; border-collapse: collapse; font-size: 13px; } | |
| table.docs th { | |
| text-align: left; color: var(--muted); font-size: 11.5px; text-transform: uppercase; | |
| letter-spacing: 0.5px; padding: 6px 8px; border-bottom: 1px solid var(--line); | |
| } | |
| table.docs td { | |
| padding: 8px; border-bottom: 1px solid #f0f1f3; vertical-align: top; | |
| overflow-wrap: anywhere; | |
| } | |
| table.docs tbody tr:last-child td { border-bottom: none; } | |
| table.docs td.score { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; } | |
| table.docs tbody tr:hover td { background: var(--bg); } | |
| .stat-grid { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 4px; } | |
| .stat { | |
| flex: 1; min-width: 110px; background: var(--bg); | |
| border: 1px solid var(--line); | |
| border-radius: 10px; padding: 10px 14px; | |
| } | |
| .stat .v { font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; } | |
| .stat .k { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; } | |
| .item-bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; } | |
| .item-bar-label { flex: 1; font-size: 12.5px; min-width: 0; overflow-wrap: anywhere; } | |
| .item-bar-track { flex: 1.2; background: var(--bg); border-radius: 999px; height: 10px; } | |
| .item-bar-fill { background: var(--accent); opacity: 0.85; height: 100%; border-radius: 999px; } | |
| .item-bar-val { width: 52px; text-align: right; font-variant-numeric: tabular-nums; font-size: 12.5px; font-weight: 600; } | |
| .construct-items { margin: 8px 0 0; padding-left: 20px; color: var(--muted); font-size: 12.5px; } | |
| .construct-items li { margin-bottom: 2px; } | |
| /* Anchor vectors (bipolar constructs): the opposite-pole picker + metric toggle. */ | |
| .anchor-toggle { margin-top: 14px; display: flex; flex-direction: column; gap: 3px; } | |
| .anchor-panel { | |
| margin-top: 10px; padding: 12px 14px; | |
| border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg); | |
| } | |
| .anchor-metric { | |
| margin: 12px 0 0; padding: 8px 12px; | |
| border: 1px solid var(--line); border-radius: var(--radius-sm); | |
| display: flex; gap: 18px; flex-wrap: wrap; align-items: center; | |
| } | |
| .anchor-metric legend { padding: 0 4px; } | |
| .check { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; font-size: 13.5px; } | |
| .check input { width: auto; height: auto; margin: 0; } | |
| .meta-footer { | |
| font-size: 12px; color: var(--muted); background: var(--bg); | |
| border-radius: var(--radius-sm); padding: 10px 14px; margin-top: 14px; | |
| font-variant-numeric: tabular-nums; | |
| } | |
| .meta-footer code { font-size: 11.5px; } | |
| .muted { color: var(--muted); } | |
| .small { font-size: 12.5px; } | |
| .mt { margin-top: 12px; } | |
| /* ---------- project header + actions ---------- */ | |
| .project-header { | |
| display: flex; align-items: center; justify-content: space-between; | |
| gap: 12px; margin-bottom: 14px; flex-wrap: wrap; | |
| } | |
| .project-title { font-size: 17px; font-weight: 650; margin-right: 10px; } | |
| button.danger { color: var(--err); border-color: #f0c4be; } | |
| button.danger:hover { color: var(--err); border-color: var(--err); } | |
| button.danger-solid { background: var(--err); } | |
| button.danger-solid:hover { background: #93261b; } | |
| button.danger-solid:disabled { background: #c9ccd1; } | |
| /* ---------- construct picker (searchable, grouped) ---------- */ | |
| .picker { position: relative; } | |
| .picker-display { | |
| width: 100%; display: flex; align-items: center; gap: 10px; | |
| padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm); | |
| background: #fff; font: inherit; color: var(--ink); cursor: pointer; text-align: left; | |
| } | |
| .picker-display:hover { border-color: var(--brand); } | |
| .picker-display .picker-caret { margin-left: auto; color: var(--muted); font-size: 11px; } | |
| .picker-search { | |
| width: 100%; padding: 8px 12px; border: 1px solid var(--brand); | |
| border-radius: var(--radius-sm); font: inherit; background: #fff; | |
| } | |
| .picker-search:focus { outline: none; box-shadow: 0 0 0 3px rgba(51, 155, 152, 0.15); } | |
| .picker-panel { | |
| position: absolute; top: calc(100% + 6px); left: 0; z-index: 50; | |
| width: 100%; max-width: 640px; | |
| background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); | |
| box-shadow: var(--shadow-lg); | |
| max-height: 340px; overflow-y: auto; padding: 4px 0 6px; | |
| animation: float-in 0.14s ease-out; | |
| } | |
| @keyframes float-in { | |
| from { opacity: 0; transform: translateY(-4px); } | |
| } | |
| .picker-group { | |
| font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.6px; | |
| color: var(--muted); padding: 8px 12px 3px; position: sticky; top: 0; | |
| background: var(--card); | |
| } | |
| .picker-option { | |
| display: flex; align-items: baseline; justify-content: space-between; gap: 12px; | |
| padding: 6px 12px; cursor: pointer; font-size: 13.5px; | |
| } | |
| .picker-option:hover, .picker-option.active { background: var(--accent-soft); } | |
| .picker-option.selected .picker-name { font-weight: 650; color: var(--brand); } | |
| .picker-name { min-width: 0; } | |
| .picker-meta { flex-shrink: 0; font-size: 11.5px; color: var(--muted); white-space: nowrap; } | |
| .picker-empty { padding: 12px; margin: 0; } | |
| /* Delete control on a custom construct row. Reserved space (opacity, not | |
| display) so rows do not reflow on hover; always visible to keyboard focus. */ | |
| .picker-delete { | |
| flex-shrink: 0; border: 0; background: none; cursor: pointer; | |
| color: var(--muted); font-size: 15px; line-height: 1; | |
| padding: 0 2px; opacity: 0; transition: opacity 0.12s, color 0.12s; | |
| } | |
| .picker-option:hover .picker-delete, .picker-delete:focus-visible { opacity: 1; } | |
| .picker-delete:hover, .picker-delete:focus-visible { color: var(--err); } | |
| .modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 18px; } | |
| /* ---------- modal ---------- */ | |
| .modal-backdrop { | |
| position: fixed; inset: 0; background: rgba(20, 22, 26, 0.4); | |
| backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); | |
| display: flex; align-items: center; justify-content: center; z-index: 40; padding: 16px; | |
| } | |
| .modal { | |
| background: var(--card); border-radius: 14px; padding: 26px 28px 24px; | |
| width: 100%; max-width: 460px; box-shadow: var(--shadow-lg); | |
| animation: modal-in 0.16s ease-out; | |
| } | |
| @keyframes modal-in { | |
| from { opacity: 0; transform: translateY(6px) scale(0.985); } | |
| } | |
| .modal h3 { margin: 0 0 8px; font-size: 18px; } | |
| /* Auth modal: roomier fields and clearer separation between sections. */ | |
| .modal .hint { color: var(--muted); font-size: 13px; line-height: 1.5; margin: 0 0 4px; } | |
| .modal form.mt { margin-top: 18px; } | |
| .modal label.field { margin-bottom: 16px; } | |
| .modal label.field:last-of-type { margin-bottom: 20px; } | |
| .modal .row { gap: 10px; } | |
| .modal .row > .primary { flex: 1; } | |
| .modal p.small.muted.mt { | |
| margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); | |
| font-size: 12.5px; line-height: 1.6; | |
| } | |
| @media (max-width: 820px) { | |
| body { font-size: 14px; } | |
| .topline { | |
| padding: 10px 14px; | |
| gap: 10px; | |
| } | |
| .topline-nav { gap: 12px; } | |
| .top-link { font-size: 13px; } | |
| .top-name { display: none; } /* the sidebar names the account; this is chrome */ | |
| .layout { display: block; } | |
| /* The sidebar becomes a drawer over the workspace. It used to be a | |
| full-width block stacked above it, which put the project list between you | |
| and the thing you had just opened on every phone visit. */ | |
| .sidebar { | |
| position: fixed; top: 0; left: 0; bottom: 0; z-index: 45; | |
| width: min(290px, 84vw); | |
| margin-left: 0; | |
| padding: 10px 12px 14px; | |
| background: var(--card); | |
| border-right: 1px solid var(--line); | |
| box-shadow: var(--shadow-lg); | |
| transform: translateX(-100%); | |
| transition: transform 0.2s ease; | |
| } | |
| .layout:not(.sidebar-closed) .sidebar { transform: translateX(0); } | |
| /* the desktop collapse rule must not also apply here */ | |
| .layout.sidebar-closed .sidebar { margin-left: 0; } | |
| .project-list { margin-right: 0; } | |
| .project-create { border-top: 0; } | |
| .sidebar-backdrop { | |
| display: block; position: fixed; inset: 0; z-index: 44; | |
| background: rgba(20, 22, 26, 0.4); | |
| backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); | |
| } | |
| .main { | |
| width: 100%; | |
| padding: 16px 14px 28px; | |
| overflow: visible; | |
| } | |
| .card { | |
| padding: 16px; | |
| margin-bottom: 14px; | |
| } | |
| .row, | |
| .run-settings, | |
| .construct-row, | |
| .results-toolbar, | |
| .result-actions { | |
| gap: 10px; | |
| } | |
| .row, | |
| .results-toolbar, | |
| .result-actions { | |
| flex-direction: column; | |
| align-items: stretch; | |
| } | |
| .run-settings, | |
| .construct-row { | |
| grid-template-columns: 1fr; | |
| } | |
| .row > .grow, | |
| .construct-row > .grow, | |
| .language-control, | |
| .model-control { | |
| width: 100%; | |
| min-width: 0; | |
| } | |
| .main .row > button, | |
| .main .row > a, | |
| .main .row > a > button, | |
| .results-toolbar > button { | |
| align-self: stretch; | |
| margin-bottom: 0; | |
| width: 100%; | |
| } | |
| /* ...except the project's own Archive/Delete pair, which read as a tall | |
| ragged column at the top of the page. They stay side by side. */ | |
| .project-header .row { flex-direction: row; justify-content: flex-end; } | |
| .project-header .row > button { width: auto; align-self: auto; } | |
| .run-button { | |
| width: 100%; | |
| min-width: 0; | |
| } | |
| .stat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); } | |
| .stat { min-width: 0; } | |
| .item-bar-row { | |
| display: grid; | |
| grid-template-columns: minmax(0, 1fr) 56px; | |
| gap: 6px 10px; | |
| } | |
| .item-bar-track { grid-column: 1 / -1; width: 100%; } | |
| .item-bar-val { width: auto; } | |
| table.docs { min-width: 520px; } | |
| } | |
| @media (max-width: 460px) { | |
| .stat-grid { grid-template-columns: 1fr; } | |
| } | |
| /* ---------- empty state (no projects yet) ---------- */ | |
| .empty-state { | |
| text-align: center; | |
| max-width: 560px; | |
| margin: 48px auto 0; | |
| padding: 36px 28px 28px; | |
| } | |
| .empty-state h3 { font-size: 17px; } | |
| .empty-state .hint { font-size: 13px; } | |
| .empty-actions { | |
| display: flex; gap: 16px; align-items: center; justify-content: center; | |
| flex-wrap: wrap; margin: 18px 0 16px; | |
| } | |
| .ghost-link { color: var(--brand); font-weight: 600; text-decoration: none; } | |
| .ghost-link:hover { text-decoration: underline; } | |
| /* ------------------------------------------------------------- welcome */ | |
| .welcome { padding-top: 1.2rem; } | |
| .welcome-hero { | |
| padding: 26px 28px; | |
| background: linear-gradient(135deg, #ffffff 55%, var(--accent-soft)); | |
| } | |
| .welcome-hero h2 { margin: 0 0 .6rem; font-size: 1.5rem; } | |
| .welcome-hero p { max-width: 62ch; } | |
| .welcome-cta { | |
| display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; | |
| margin: 1.1rem 0 .6rem; | |
| } | |
| .welcome-cta .ghost-link { font-size: .95rem; } | |
| .welcome-steps { | |
| display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; | |
| } | |
| .welcome-step h3 { margin: .2rem 0 .3rem; } | |
| .step-n { | |
| width: 1.9rem; height: 1.9rem; border-radius: 50%; | |
| background: var(--brand); color: #fff; font-weight: 700; | |
| display: flex; align-items: center; justify-content: center; | |
| } | |
| @media (max-width: 700px) { | |
| .welcome-steps { grid-template-columns: 1fr; } | |
| /* Runs table on a phone: every column after Construct fell off the right | |
| edge, so Status and View results - the two things you open the table for - | |
| needed a sideways scroll (reported 2026-09-08). Each run becomes a stacked | |
| card: no horizontal scroll and nothing dropped. Cells label themselves from | |
| data-label, because the header row cannot apply once rows are blocks. | |
| Scoped to .runs-table, NOT every .docs table: the results tables have no | |
| data-label attributes and would stack with blank labels. | |
| Two things measured rather than guessed: the base rules are `table.docs td`, | |
| which outranks a bare `.docs td`; and the 820px block above sets | |
| `table.docs { min-width: 520px }` to force these tables to scroll, which | |
| kept the row 520px wide inside a 328px wrapper until it is reset here. */ | |
| table.docs.runs-table { min-width: 0; width: 100%; max-width: 100%; } | |
| table.docs.runs-table thead { display: none; } | |
| table.docs.runs-table, | |
| table.docs.runs-table tbody, | |
| table.docs.runs-table tr, | |
| table.docs.runs-table td { display: block; } | |
| table.docs.runs-table tr { | |
| border: 1px solid var(--line); border-radius: var(--radius-sm); | |
| padding: 10px 12px; margin-bottom: 10px; max-width: 100%; | |
| } | |
| table.docs.runs-table tbody tr:hover td { background: none; } | |
| table.docs.runs-table td { | |
| padding: 3px 0; border-bottom: 0; text-align: left; | |
| max-width: 100%; overflow-wrap: anywhere; | |
| } | |
| table.docs.runs-table td::before { | |
| content: attr(data-label); display: inline-block; min-width: 88px; | |
| color: var(--muted); font-size: 11.5px; text-transform: uppercase; | |
| letter-spacing: 0.4px; | |
| } | |
| table.docs.runs-table td[data-label=""] { padding-top: 8px; } | |
| table.docs.runs-table td[data-label=""]::before { content: none; } | |
| /* Results tables on a phone (reported 2026-09-09, same complaint as the runs | |
| table). The 820px block sets `table.docs { min-width: 520px }` so wide | |
| tables scroll rather than squash - right for the admin tables, wrong for | |
| these two, which sit in a 328px card and so ALWAYS needed a sideways drag: | |
| - texts-table is Score + Text. Two columns fit once the text is allowed | |
| to wrap, so there is nothing to scroll to. | |
| - corr-table is the interrelations matrix. Two or three constructs now | |
| fit; a wider matrix still scrolls inside .table-wrap, which is what a | |
| matrix has to do on any screen. | |
| Score stays on one line so the numbers keep their column. */ | |
| table.docs.texts-table, | |
| table.docs.corr-table { min-width: 0; } | |
| table.docs.texts-table th:first-child, | |
| table.docs.texts-table td.score { width: 52px; } | |
| table.docs.corr-table th, | |
| table.docs.corr-table td { padding: 6px 5px; } | |
| /* Disclosure rows (a selected construct in Step 2, a construct's section in | |
| multi-construct results). The meta line after the name is nowrap, so on a | |
| phone it ran past the right edge and took the WHOLE PAGE sideways with it - | |
| the multi-construct results page scrolled to 485px inside a 390px screen. | |
| It gets its own line under the name instead. */ | |
| .construct-selected summary, | |
| .construct-results summary { flex-wrap: wrap; } | |
| .construct-selected summary .picker-meta, | |
| .construct-results summary .picker-meta { | |
| white-space: normal; margin-left: 0; flex: 1 1 100%; | |
| } | |
| .construct-selected summary .construct-remove { margin-left: auto; } | |
| } | |
| /* ------------------------------------------- multi-construct runs */ | |
| .construct-selected { | |
| margin-top: 8px; border: 1px solid var(--line); border-radius: var(--radius-sm); | |
| padding: 8px 12px; background: #fff; | |
| } | |
| .construct-selected summary, | |
| .construct-results summary { | |
| cursor: pointer; display: flex; align-items: baseline; gap: 8px; | |
| list-style: none; | |
| } | |
| .construct-selected summary::-webkit-details-marker, | |
| .construct-results summary::-webkit-details-marker { display: none; } | |
| .construct-selected summary::before, | |
| .construct-results summary::before { | |
| content: "\25B8"; color: var(--muted); font-size: 11px; | |
| transition: transform 0.15s ease; align-self: center; | |
| } | |
| details[open] > summary::before { transform: rotate(90deg); } | |
| .construct-selected-name { font-weight: 600; font-size: 13.5px; } | |
| .construct-remove { margin-left: auto; flex-shrink: 0; } | |
| .construct-results summary .picker-meta { margin-left: 6px; } | |
| .construct-results h4 { margin: 14px 0 4px; font-size: 13.5px; } | |
| /* New-construct panel: a contained sub-card so the form reads as one unit, | |
| visually separate from the picker above it. */ | |
| .new-construct { | |
| border: 1px solid var(--line); | |
| border-radius: var(--radius-sm); | |
| padding: 14px 16px 16px; | |
| margin-top: 12px; | |
| background: var(--bg); | |
| } | |
| .new-construct-head { | |
| display: flex; align-items: center; justify-content: space-between; | |
| margin-bottom: 10px; | |
| } | |
| /* The three item sources as radio-cards - one glance, one choice, and only | |
| the chosen path's fields render below (tester feedback: the flat form with | |
| every path's controls stacked read as clutter). */ | |
| .source-cards { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); | |
| gap: 10px; | |
| margin: 0 0 14px; | |
| } | |
| .source-card { | |
| text-align: left; | |
| padding: 10px 12px; | |
| border: 1.5px solid var(--line); | |
| border-radius: var(--radius-sm); | |
| background: var(--card); | |
| cursor: pointer; | |
| font: inherit; | |
| color: var(--ink); | |
| transition: border-color .12s, background .12s; | |
| } | |
| .source-card:hover { border-color: var(--accent); } | |
| .source-card.active { border-color: var(--brand); background: var(--accent-soft); } | |
| .source-card b { display: block; font-size: 13.5px; margin-bottom: 2px; } | |
| .source-card span { display: block; font-size: 12px; color: var(--muted); line-height: 1.35; } | |
| /* Controls + button on one baseline (the plain .row leaves the button 10px | |
| low because label.field carries a bottom margin). */ | |
| .field-row { display: flex; gap: 14px; align-items: end; flex-wrap: wrap; } | |
| .field-row .field { margin-bottom: 0; } | |
| .field-row > .small { align-self: center; margin: 0 0 8px; } | |
| /* "Drafted by <model>" line + hover/focus info bubble in the AI construct | |
| path. The model name is read live from the API (auth.generation), so the UI | |
| never hardcodes it. */ | |
| .ai-modeline { | |
| display: flex; align-items: center; gap: 8px; | |
| margin: 2px 0 10px; | |
| } | |
| .infotip { | |
| position: relative; | |
| display: inline-flex; align-items: center; justify-content: center; | |
| padding: 0; border: none; background: none; cursor: help; | |
| font: inherit; line-height: 1; | |
| } | |
| .infotip-icon { | |
| display: inline-flex; align-items: center; justify-content: center; | |
| width: 16px; height: 16px; border-radius: 50%; | |
| background: var(--accent-soft); color: var(--brand); | |
| border: 1px solid var(--brand); font-size: 11px; font-weight: 700; | |
| font-style: normal; | |
| } | |
| .infotip:hover .infotip-icon, | |
| .infotip:focus-visible .infotip-icon { background: var(--brand); color: #fff; } | |
| .infotip:focus-visible { outline: none; } | |
| .infotip:focus-visible .infotip-icon { box-shadow: var(--ring); } | |
| .infotip-pop { | |
| position: absolute; left: 0; top: calc(100% + 8px); z-index: 40; | |
| width: 300px; max-width: 78vw; | |
| padding: 10px 12px; | |
| background: var(--card); color: var(--ink); | |
| border: 1px solid var(--line); border-radius: var(--radius-sm); | |
| box-shadow: var(--shadow-md); | |
| font-size: 12px; line-height: 1.45; text-align: left; | |
| /* reset the base `button { white-space: nowrap }` so the bubble text wraps | |
| inside its fixed width instead of overflowing the box */ | |
| white-space: normal; overflow-wrap: anywhere; | |
| opacity: 0; visibility: hidden; transform: translateY(-3px); | |
| transition: opacity .12s, transform .12s, visibility .12s; | |
| pointer-events: none; | |
| } | |
| .infotip:hover .infotip-pop, | |
| .infotip:focus-within .infotip-pop { | |
| opacity: 1; visibility: visible; transform: translateY(0); | |
| } | |
| .infotip-pop b { display: block; margin-bottom: 4px; color: var(--brand-ink); } | |
| .infotip-pop ul { margin: 0; padding-left: 16px; } | |
| .infotip-pop li { margin: 2px 0; color: var(--ink); } | |
| .infotip-pop a { display: inline-block; margin-top: 6px; color: var(--brand); font-weight: 600; } | |
| /* Site identity footer: present on every page (see App.jsx). Deliberately | |
| plain text rather than an icon row, because its job is to be readable by | |
| whatever is looking, including clients that never run the JS bundle. */ | |
| .site-footer { | |
| max-width: 920px; | |
| margin: 40px auto 0; | |
| padding: 18px 1rem 28px; | |
| border-top: 1px solid var(--line); | |
| color: var(--muted); | |
| font-size: 12.5px; | |
| line-height: 1.6; | |
| } | |
| .site-footer p { margin: 0 0 6px; } | |
| .site-footer p:last-child { margin-bottom: 0; } | |
| .site-footer strong { color: var(--ink); } | |
| .site-footer a { color: var(--brand); text-decoration: none; } | |
| .site-footer a:hover { text-decoration: underline; } | |
| @media (prefers-reduced-motion: reduce) { | |
| .sidebar { transition: none; } | |
| .infotip-pop { transition: none; } | |
| .picker-panel, .modal { animation: none; } | |
| .pill.running::before { animation: none; } | |
| .construct-selected summary::before, | |
| .construct-results summary::before { transition: none; } | |
| button.primary:active, button.ghost:active, a.ghost:active { transform: none; } | |
| } | |
| /* Anonymous "sign in to keep it" notice after saving a custom construct. | |
| Deliberately a hint, not a warning: the work succeeded, this is only about | |
| how long it lasts. */ | |
| .keep-notice { | |
| margin-top: 12px; padding: 10px 12px; border-radius: 8px; | |
| background: var(--accent-soft); border: 1px solid var(--border); | |
| } | |
| .linklike { | |
| border: 0; background: none; padding: 0; cursor: pointer; | |
| color: var(--brand); text-decoration: underline; font: inherit; | |
| } | |
| /* ---------- sample corpora (Step 1) ---------- | |
| The second branch of Step 1, not a panel bolted under it. An "or" rule | |
| separates it from the upload row, and it reuses the same .field label + | |
| control shape as the fields above, so it reads as part of the form. It | |
| previously sat in a grey slab inside the white card, which looked patched | |
| on. Always visible: collapsed behind a toggle the corpus was never named on | |
| screen, and neither the PI nor a lab member could find CAMEL (2026-09-08). */ | |
| .or-rule { | |
| display: flex; align-items: center; gap: 14px; | |
| margin: 18px 0 16px; color: var(--muted); font-size: 11.5px; | |
| text-transform: uppercase; letter-spacing: 0.8px; | |
| } | |
| .or-rule::before, .or-rule::after { | |
| content: ""; flex: 1; height: 1px; background: var(--line); | |
| } | |
| .samples { max-width: 640px; } | |
| .samples-field { margin-bottom: 0; } | |
| .samples-row { display: flex; align-items: center; gap: 8px; margin-top: 4px; } | |
| .samples-row select { flex: 1; min-width: 0; } | |
| .samples-row button { flex-shrink: 0; } | |
| /* The "i" is sized to the control height and shares the field radius, so the | |
| row reads as three parts of one control rather than three unrelated shapes. */ | |
| button.info-button { | |
| width: var(--control-height); padding: 0; border-radius: var(--radius-sm); | |
| font-family: Georgia, "Times New Roman", serif; font-style: italic; | |
| font-size: 15px; color: var(--muted); | |
| } | |
| .samples-detail { margin: 8px 0 0; } | |
| .modal-wide { max-width: 560px; } | |
| /* Dataset mark in the corpus info dialog. Decorative (alt=""): the name is | |
| right beside it, so a screen reader announcing the logo would just repeat. */ | |
| .modal-head { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; } | |
| .modal-head h3 { margin: 0; } | |
| .corpus-logo { height: 34px; width: auto; flex-shrink: 0; } | |
| /* ---------- cite dialog ---------- | |
| Google Scholar's Cite panel, in this app's language (Ali Hajian, 2026-09-09): | |
| a style name on the left, the reference on the right, the whole row a copy | |
| button. Rows are <button>s rather than a div with a click handler, so they | |
| are reachable by keyboard and announce themselves. */ | |
| .cite-modal { max-width: 620px; max-height: min(86vh, 900px); overflow-y: auto; } | |
| .cite-modal .modal-head { justify-content: space-between; align-items: baseline; } | |
| .cite-close { | |
| font-size: 15px; color: var(--muted); line-height: 1; text-decoration: none; | |
| } | |
| .cite-close:hover { color: var(--ink); } | |
| /* The dialog takes focus on open so Escape and the arrow keys land somewhere | |
| sensible; that is a programmatic focus, not a keyboard one, so it should not | |
| paint a ring around the whole panel. Rows keep their own focus ring. */ | |
| .cite-modal:focus { outline: none; } | |
| .cite-list { border-top: 1px solid var(--line); margin-top: 6px; } | |
| .cite-row { | |
| display: grid; | |
| grid-template-columns: 74px minmax(0, 1fr) 52px; | |
| gap: 12px; | |
| align-items: start; | |
| width: 100%; | |
| padding: 11px 6px; | |
| border: 0; border-bottom: 1px solid var(--line); | |
| background: none; font: inherit; text-align: left; cursor: pointer; | |
| /* the base `button { white-space: nowrap }` would push the reference out | |
| of the dialog instead of wrapping it */ | |
| white-space: normal; | |
| } | |
| .cite-row:hover { background: var(--bg); } | |
| .cite-style { | |
| color: var(--muted); font-size: 11.5px; text-transform: uppercase; | |
| letter-spacing: 0.5px; text-align: right; padding-top: 2px; | |
| } | |
| .cite-text { font-size: 13px; line-height: 1.55; overflow-wrap: anywhere; } | |
| .cite-copied { | |
| color: var(--ok); font-size: 11.5px; font-weight: 600; text-align: right; | |
| padding-top: 2px; | |
| } | |
| .cite-also { | |
| margin-top: 14px; padding: 10px 14px; | |
| background: var(--bg); border: 1px solid var(--line); | |
| border-radius: var(--radius-sm); | |
| font-size: 12.5px; line-height: 1.55; color: var(--muted); | |
| } | |
| .cite-also b { color: var(--ink); } | |
| .cite-also ul { margin: 8px 0 0; padding-left: 18px; } | |
| .cite-also li { margin-bottom: 6px; overflow-wrap: anywhere; } | |
| .cite-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; } | |
| .cite-export { margin-top: 12px; } | |
| .cite-export pre { | |
| background: var(--bg); border: 1px solid var(--line); | |
| border-radius: var(--radius-sm); padding: 10px 12px; margin: 0 0 10px; | |
| font-size: 11.5px; line-height: 1.5; | |
| max-height: 260px; overflow: auto; | |
| /* wrap rather than scroll sideways: these are long author lines, and a | |
| phone should not need two directions of scrolling to read them */ | |
| white-space: pre-wrap; overflow-wrap: anywhere; | |
| } | |
| /* Cite dialog on a phone. This block has to live AFTER the base .cite-* rules | |
| rather than in the 700px block above: same specificity, so whichever comes | |
| last in the file wins, and the overrides silently lost from up there | |
| (measured, not assumed). A 74px style column leaves the reference about | |
| 110px wide at 360px, so the style name moves above the reference and | |
| "Copied" sits beside the style name. */ | |
| @media (max-width: 700px) { | |
| .cite-row { grid-template-columns: minmax(0, 1fr) 56px; gap: 2px 10px; } | |
| .cite-style { text-align: left; grid-column: 1; grid-row: 1; } | |
| .cite-copied { grid-column: 2; grid-row: 1; } | |
| .cite-text { grid-column: 1 / -1; } | |
| .cite-actions > button { flex: 1 1 100%; } | |
| } | |