@charset "UTF-8";
/* Font Faces - Playfair Display (Serif) */
@font-face {
  font-family: "Playfair Display";
  src: url("/static/font/Playfair_static/PlayfairDisplay-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Playfair Display";
  src: url("/static/font/Playfair_static/PlayfairDisplay-Italic.ttf") format("truetype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Playfair Display";
  src: url("/static/font/Playfair_static/PlayfairDisplay-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Playfair Display";
  src: url("/static/font/Playfair_static/PlayfairDisplay-BoldItalic.ttf") format("truetype");
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}
/* Font Faces - Quicksand (Sans-Serif) */
@font-face {
  font-family: "Quicksand";
  src: url("/static/font/Quickstand_static/Quicksand-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Quicksand";
  src: url("/static/font/Quickstand_static/Quicksand-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
/* Font Faces - Source Code Pro (Monospace) */
@font-face {
  font-family: "Source Code Pro";
  src: url("/static/font/SourceCodePro_static/SourceCodePro-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Code Pro";
  src: url("/static/font/SourceCodePro_static/SourceCodePro-Italic.ttf") format("truetype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Source Code Pro";
  src: url("/static/font/SourceCodePro_static/SourceCodePro-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Code Pro";
  src: url("/static/font/SourceCodePro_static/SourceCodePro-BoldItalic.ttf") format("truetype");
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}
/* Base font stack */
:root {
  --font-serif: "Playfair Display", Georgia, "Times New Roman", serif;
  --font-sans-serif: "Quicksand", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-monospace: "Source Code Pro", "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
}

:root {
  --palette-brand-dark: oklch(0.35 0.045 260);
  --palette-brand-medium: oklch(0.46 0.055 260);
  --palette-brand-light: oklch(0.9 0.02 250);
  --palette-gray-900: oklch(0.24 0.006 260);
  --palette-gray-800: oklch(0.3 0.006 260);
  --palette-gray-700: oklch(0.42 0.008 260);
  --palette-gray-600: oklch(0.55 0.01 260);
  --palette-gray-500: oklch(0.63 0.012 260);
  --palette-gray-400: oklch(0.75 0.01 260);
  --palette-gray-300: oklch(0.85 0.008 260);
  --palette-gray-200: oklch(0.89 0.006 260);
  --palette-gray-100: oklch(0.93 0.005 260);
  --palette-gray-75: oklch(0.96 0.004 260);
  --palette-gray-50: oklch(0.98 0.003 260);
  --palette-primary-dark: oklch(0.37 0.15 258);
  --palette-primary-focus: oklch(0.52 0.2 258);
  --palette-primary: oklch(0.58 0.22 250);
  --palette-primary-hover: oklch(0.7 0.15 244);
  --palette-primary-lighter: oklch(0.87 0.06 245);
  --palette-primary-light: oklch(0.96 0.02 250);
  --palette-danger-dark: oklch(0.32 0.12 22);
  --palette-danger-dark-hover: oklch(0.4 0.14 22);
  --palette-danger: oklch(0.58 0.2 25);
  --palette-danger-hover: oklch(0.62 0.2 27);
  --palette-danger-light: oklch(0.9 0.045 20);
  --palette-danger-lighter: oklch(0.97 0.012 25);
  --palette-success-dark: oklch(0.35 0.1 145);
  --palette-success: oklch(0.62 0.16 145);
  --palette-success-hover: oklch(0.68 0.15 145);
  --palette-success-light: oklch(0.92 0.045 145);
  --palette-warning-dark: oklch(0.5 0.11 78);
  --palette-warning: oklch(0.85 0.17 90);
  --palette-warning-lighter: oklch(0.97 0.075 92);
  --palette-warning-light: oklch(0.97 0.055 92);
  --palette-info-dark: oklch(0.57 0.02 250);
  --palette-purple: oklch(0.53 0.22 300);
  --palette-purple-light: oklch(0.88 0.05 305);
  --palette-link-blue: oklch(0.52 0.18 250);
  --palette-link-violet: oklch(0.44 0.18 300);
}

/* Default body font (sans-serif) */
body {
  font-family: var(--font-sans-serif);
}

/* Headers use serif font */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-serif);
}

/* Monospace elements */
code, kbd, samp, pre {
  font-family: var(--font-monospace);
}

/* Utility classes */
.font-serif {
  font-family: var(--font-serif);
}

.font-sans-serif {
  font-family: var(--font-sans-serif);
}

.font-monospace {
  font-family: var(--font-monospace);
}

.select-all {
  user-select: all;
}

/* Link that looks like regular text */
.stealth-link {
  color: inherit;
  text-decoration: none;
}

.stealth-link:hover {
  text-decoration: none;
  opacity: 0.8;
}

.link-unvisited {
  color: oklch(0.52 0.18 250);
  text-decoration: underline;
  text-decoration-style: solid;
}

.link-visited {
  color: oklch(0.44 0.18 300);
  text-decoration: underline;
  text-decoration-style: dashed;
}

.basic-page {
  padding: 1rem;
  max-width: 800px;
  margin: 0 auto;
}

/* Home page hero photograph.

   The figure sits outside `.basic-page` so it can reach both edges of the
   viewport while the text column below it keeps its 800px cap. */
.home-hero {
  margin: 0;
  width: 100%;
  /* The source is 3:2. A letterbox band reads as a header rather than as a
   picture dropped on the page, and `object-fit: cover` does the crop. */
  aspect-ratio: 21/9;
  /* On a short window the band would otherwise eat the whole first screen. */
  max-height: 60vh;
  overflow: hidden;
  /* Shows while the image decodes, so the band does not flash white. */
  background: oklch(0.24 0.006 260);
  /* Anchors the headline to the photograph. */
  position: relative;
}

.home-hero-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Keeps both actors' heads and the bench they sit on inside the band. A
   plain centre crop loses the bench; anything lower cuts the standing
   actor's head off. */
  object-position: center 55%;
}

/* The headline over the photograph: right-justified, settled on the bottom. */
.home-hero-title {
  position: absolute;
  /* Fills the band so the flex alignment below has the full height and width
   to push against. */
  inset: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  /* Bottom of the band. */
  justify-content: flex-end;
  /* Right of the band. */
  align-items: flex-end;
  text-align: right;
  /* A quarter of the band's height.

   The band is `min(100vw * 9/21, 60vh)` — see `.home-hero` above — so a
   quarter of it is `min(10.714vw, 15vh)`. The two numbers restate the
   aspect ratio and the height cap, so change them together with the ones
   on `.home-hero`.

   Container query units (`25cqh`) would say this directly, but they need
   `container-type: size` on the band, and that stops the photograph
   painting at all in Chromium. */
  font-size: min(10.714vw, 15vh);
  /* Display type at this size needs far tighter leading than body copy, and
   the two lines have to stack as one block. */
  line-height: 0.95;
  /* Playfair Display, via the shared heading rule; stated again because this
   is a design decision here, not an inherited default. */
  font-family: var(--font-serif);
  font-weight: 700;
  color: #fff;
  /* The photograph is busy, and the crop moves under a narrow viewport. The
   shadow keeps the text legible over whatever ends up behind it. */
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.75);
  padding: 0 3vw 2vh;
  /* The headline is decoration over a photograph; the pointer belongs to
   anything underneath it. */
  pointer-events: none;
}

.home-hero-line {
  display: block;
  /* The line breaks in the headline are authored, not found. A line that
   reflows would restack the whole block and break the quarter-height
   proportion, so it never wraps. */
  white-space: nowrap;
}

/* Narrow screens get a taller crop: at 21:9 a phone-width band is only about
   160px tall, too short to read as a photograph at all. */
@media (max-width: 48rem) {
  .home-hero {
    aspect-ratio: 4/3;
    max-height: 45vh;
  }
  /* A strict quarter of the narrow-screen band is `min(18.75vw, 11.25vh)`,
   and at that size the longest line runs off the screen: "Phrase Here" is
   5.66em wide, which needs a viewport about 1.5x wider than a phone. So the
   narrow-screen size is capped at what fits the width instead — about a
   fifth of the band rather than a quarter. The alternative is a headline
   that wraps to three lines and fills the whole photograph. */
  .home-hero-title {
    font-size: min(12.5vw, 11.25vh);
  }
}
.home-page {
  padding-top: 2rem;
  /* Wider than the 800px `.basic-page` default. Three columns inside 800px
   leave about 230px each, which is too narrow for the copy to read as
   columns rather than as slivers. */
  max-width: 60rem;
}

/* The three columns of copy under the tagline. */
.home-columns {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Half of the space between two columns. The other half comes from the
   padding on the rule below, so the rule sits centred in the channel. */
  gap: 2.5rem;
  margin: 3rem 0;
}

/* Each column draws the rule on its own leading edge, so the first column has
   none and there is one line between each pair. No divider elements in the
   markup, so a screen reader has nothing extra to announce. */
.home-column + .home-column {
  border-inline-start: 1px solid oklch(0.89 0.006 260);
  padding-inline-start: 2.5rem;
}

.home-column-heading {
  margin: 0 0 0.5rem;
  font-size: 1.25rem;
}

.home-column-copy {
  margin: 0;
  /* Slightly looser than the body default; a narrow measure needs the air. */
  line-height: 1.6;
  color: oklch(0.3 0.006 260);
}

/* The product name, wherever it appears in body copy. Bold and italic, so it
   reads as a name rather than as another noun in the sentence. */
.product-name {
  font-weight: 700;
  font-style: italic;
}

/* Two columns of copy, each flowing around a cut-out image. */
.home-wrap {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2.5rem;
  margin: 3rem 0;
}

.home-wrap-column p {
  margin: 0 0 1rem;
  line-height: 1.6;
  color: oklch(0.3 0.006 260);
}

/* Only the very last paragraph of the section loses its bottom margin. Scoping
   this to `.home-wrap-column p:last-child` instead would zero the margin at the
   join between the two columns, and on a narrow screen — where the columns
   stack — that join is mid-flow, so two paragraphs would run together. */
.home-wrap-column:last-child p:last-child {
  margin-bottom: 0;
}

.home-wrap-image {
  width: 55%;
  height: auto;
}

/* `shape-outside` is the reason these images were cut out. It reads the alpha
   channel and runs the text along the subject's silhouette instead of around
   its bounding box, so the copy tucks into the angled corners.

   The URL has to be a literal, which means the plain `/static/` path rather
   than the versioned `/v/<build>/` one the markup uses. Both resolve to the
   same file; only the cache header differs, and this is decorative geometry.
   A browser that does not support the property falls back to the box, which
   still reads correctly.

   `shape-image-threshold: 0.5` treats a pixel as part of the subject once it is
   more than half opaque, which keeps the soft drop shadow on the binders out of
   the shape. */
.home-wrap-image-left {
  float: left;
  margin: 0.25rem 1.25rem 0.75rem 0;
  shape-outside: url("/static/image/commons/Stack_of_ringless_binders.avif");
  shape-image-threshold: 0.5;
  shape-margin: 0.75rem;
}

.home-wrap-image-right {
  float: right;
  margin: 0.25rem 0 0.75rem 1.25rem;
  shape-outside: url("/static/image/commons/201706_Laptop_close.avif");
  shape-image-threshold: 0.5;
  shape-margin: 0.75rem;
}

/* One column per row on a narrow screen. The rule between two columns turns
   from a vertical line in a channel into a horizontal one between stacked
   blocks, so it moves from the leading edge to the top.

   This block sits after the rules it overrides on purpose. The same breakpoint
   for the hero appears earlier in the file, and putting these there instead
   would place them ABOVE `.home-columns` — same specificity, so the
   three-column rule would win and the columns would never stack. */
@media (max-width: 48rem) {
  .home-columns {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .home-column + .home-column {
    border-inline-start: 0;
    padding-inline-start: 0;
    border-top: 1px solid oklch(0.89 0.006 260);
    padding-top: 2rem;
  }
}
/* One column of copy on a narrow screen. The images keep their float, so the
   text still wraps, but they take less of the width: a 55% float in a
   single-column layout leaves a measure too narrow to read. */
@media (max-width: 48rem) {
  .home-wrap {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .home-wrap-image {
    width: 42%;
  }
}
/* The line under the photograph. Sized to match an h1 (2em), but it is a
   paragraph — the headline over the photograph is the page's only heading. */
.home-tagline {
  font-family: var(--font-serif);
  font-size: 2em;
  text-align: center;
  color: oklch(0.24 0.006 260);
  margin: 0 0 2.5rem;
  /* Keeps the line from running the full width of a wide column, which reads
   badly at this size. */
  max-width: 24ch;
  margin-inline: auto;
  text-wrap: balance;
}

/* Photo credits on the About page. */
.attribution-list {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
}

.attribution-item {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  padding: 0.75rem 0;
  border-top: 1px solid oklch(0.93 0.005 260);
}

.attribution-thumb-link {
  flex: none;
  display: block;
  line-height: 0;
}

.attribution-thumb {
  width: 120px;
  height: 80px;
  object-fit: cover;
  border-radius: 4px;
}

.attribution-detail {
  flex: 1;
  min-width: 0;
}

.attribution-description {
  margin: 0;
}

.attribution-credit {
  margin: 0.25rem 0 0;
  font-size: 0.875rem;
  color: oklch(0.42 0.008 260);
}

@media (max-width: 40rem) {
  .attribution-item {
    flex-direction: column;
  }
  .attribution-thumb {
    width: 100%;
    height: auto;
    aspect-ratio: 3/2;
  }
}
.leaving-page .leaving-url {
  padding: 0.75rem 1rem;
  background-color: oklch(0.98 0.003 260);
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  word-break: break-all;
}

.leaving-page .leaving-actions {
  margin-top: 1.5rem;
  display: flex;
  gap: 0.75rem;
  align-items: center;
}

/* Help documentation pages. */
.help-layout {
  display: flex;
  min-height: calc(100vh - 60px);
}

.help-sidebar {
  flex: 0 0 250px;
  background-color: oklch(0.98 0.003 260);
  border-right: 1px solid oklch(0.93 0.005 260);
  padding: 1rem;
  overflow-y: auto;
  max-height: calc(100vh - 60px);
  position: sticky;
  top: 60px;
}

.help-sidebar-nav {
  display: flex;
  flex-direction: column;
}

.help-sidebar-title {
  margin: 0 0 0.75rem;
  font-size: 1rem;
}
.help-sidebar-title a {
  color: inherit;
  text-decoration: none;
  font-weight: 600;
}
.help-sidebar-title a.active {
  color: oklch(0.58 0.22 250);
}
.help-sidebar-title a:hover {
  color: oklch(0.58 0.22 250);
}

.help-sidebar-group {
  margin-bottom: 0.75rem;
}

.help-sidebar-group-title {
  margin: 0 0 0.25rem;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: oklch(0.63 0.012 260);
}

.help-sidebar-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.help-sidebar-list li {
  margin-bottom: 1px;
}

.help-sidebar-link {
  display: block;
  padding: 0.25rem 0.5rem;
  border-radius: 3px;
  color: oklch(0.42 0.008 260);
  text-decoration: none;
  font-size: 0.875rem;
}
.help-sidebar-link:hover {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.24 0.006 260);
}
.help-sidebar-link.active {
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.37 0.15 258);
  font-weight: 500;
}

.help-sidebar-toggle {
  display: none;
  position: fixed;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 101;
  background-color: oklch(0.98 0.003 260);
  border: 1px solid oklch(0.89 0.006 260);
  border-left: none;
  border-radius: 0 4px 4px 0;
  padding: 0.5rem 0.25rem;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  color: oklch(0.55 0.01 260);
}
.help-sidebar-toggle:hover {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.3 0.006 260);
}

.help-sidebar-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.3);
  z-index: 99;
}

.help-main {
  flex: 1;
  min-width: 0;
}

@media (max-width: 768px) {
  .help-sidebar {
    position: fixed;
    left: 0;
    top: 60px;
    bottom: 0;
    z-index: 100;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    max-height: none;
  }
  .help-sidebar-toggle {
    display: block;
  }
  .help-layout.help-sidebar-open .help-sidebar {
    transform: translateX(0);
  }
  .help-layout.help-sidebar-open .help-sidebar-backdrop {
    display: block;
  }
  .help-layout.help-sidebar-open .help-sidebar-toggle {
    display: none;
  }
}
.help-page {
  padding: 2rem;
  max-width: 800px;
  width: 100%;
}

.help-nav {
  margin-bottom: 1rem;
}

.help-topic-list {
  margin: 0.5rem 0 1.5rem;
  padding-left: 1.5rem;
}

.help-topic-list li {
  margin-bottom: 0.25rem;
}

.help-content {
  min-height: 200px;
}

.help-toc {
  margin: 0 1rem 1.5rem;
  padding: 0.75rem 1rem;
  background-color: oklch(0.98 0.003 260);
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
}

.help-toc .toc-title {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
}

.help-toc ul {
  margin: 0;
  padding-left: 1.25rem;
  list-style: none;
}

.help-toc li {
  margin-bottom: 0.2rem;
}

.help-toc .toc-level-3 {
  padding-left: 1rem;
}

.heading-anchor {
  visibility: hidden;
  font-size: 0.8em;
  color: oklch(0.75 0.01 260);
  text-decoration: none;
  margin-left: 0.3rem;
  cursor: pointer;
}

h2:hover .heading-anchor,
h3:hover .heading-anchor {
  visibility: visible;
}

.heading-anchor:hover {
  color: oklch(0.42 0.008 260);
}

.help-context-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  border: 1px solid oklch(0.75 0.01 260);
  font-size: 0.75rem;
  font-weight: 700;
  color: oklch(0.55 0.01 260);
  text-decoration: none;
  vertical-align: middle;
  margin-left: 0.4rem;
}

.help-context-btn:hover {
  color: oklch(0.42 0.008 260);
  border-color: oklch(0.55 0.01 260);
  background-color: oklch(0.98 0.003 260);
}

/* =============================================================================
   App Title Bar
   ============================================================================= */
.app-title-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 1rem;
  background: oklch(0.35 0.045 260);
  color: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  position: sticky;
  top: 0;
  z-index: 100;
}

.title-bar-left {
  display: flex;
  align-items: center;
}

.app-title {
  font-family: var(--font-serif);
  font-size: 1.5rem;
  font-weight: 700;
  color: #fff;
  text-decoration: none;
}

.app-title:hover {
  color: oklch(0.89 0.006 260);
  text-decoration: none;
}

.title-bar-nav {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.title-bar-nav .nav-link {
  color: oklch(0.89 0.006 260);
  text-decoration: none;
  font-weight: 500;
  padding: 0.25rem 0;
  border-bottom: 2px solid transparent;
  transition: border-color 0.2s, color 0.2s;
}

.title-bar-nav .nav-link:hover {
  color: #fff;
  border-bottom-color: #fff;
}

.title-bar-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.site-user-name {
  color: oklch(0.89 0.006 260);
  font-weight: 500;
}

.user-profile-link {
  color: oklch(0.89 0.006 260);
  text-decoration: none;
  font-weight: 500;
}

.user-profile-link:hover {
  color: #fff;
}

.title-bar-right .btn {
  padding: 0.375rem 0.75rem;
  border-radius: 4px;
  font-size: 0.875rem;
  text-decoration: none;
  font-weight: 500;
  transition: background-color 0.2s, opacity 0.2s;
}

.title-bar-right .btn-primary {
  background: oklch(0.7 0.15 244);
  color: #fff;
}

.title-bar-right .btn-primary:hover {
  background: oklch(0.7 0.15 244);
}

.title-bar-right .btn-secondary {
  background: transparent;
  color: oklch(0.89 0.006 260);
  border: 1px solid oklch(0.89 0.006 260);
}

.title-bar-right .btn-secondary:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}

/* User menu dropdown in title bar */
.title-bar-right .user-menu {
  position: relative;
}

.title-bar-right .user-menu .dropdown-toggle {
  background: transparent;
  border: none;
  color: oklch(0.89 0.006 260);
  cursor: pointer;
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
}

.title-bar-right .user-menu .dropdown-toggle:hover {
  color: #fff;
}

.title-bar-right .user-menu .dropdown-menu {
  position: absolute;
  top: 100%;
  right: 0;
  left: auto;
  transform: translateX(0);
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  min-width: 150px;
  max-width: calc(100vw - 1rem);
  display: none;
  z-index: 110;
}

.title-bar-right .user-menu .dropdown-menu.open {
  display: block;
}

.title-bar-right .user-menu .dropdown-item {
  display: block;
  padding: 0.5rem 1rem;
  color: oklch(0.35 0.045 260);
  text-decoration: none;
}

.title-bar-right .user-menu .dropdown-item:hover {
  background: oklch(0.98 0.003 260);
}

/* App content area (below title bar). Sits at a subtle gray-50 tint so
   centered content columns (documents-page, story-content, etc.) can pop
   forward on white with the edge-delineation treatment. */
.app-content {
  /* padding: 1rem; */
  min-height: calc(100vh - 60px);
  display: flex;
  flex-direction: column;
  background: oklch(0.98 0.003 260);
}

/* Center-content edge treatment: 1px vertical rules pinned to each edge of
   the content column plus a soft outer glow. Reads as "a page floating in a
   gutter" without introducing a card frame. `flex: 1` makes the column
   extend to fill its (flex-column) parent so short content still reaches
   the footer edge instead of ending mid-gutter. Applied via a mixin so any
   full-width layout with a max-width'd centered column can opt in. */
/* Site content area for public (non-app) pages */
.site-content {
  min-height: calc(100vh - 60px);
  display: flex;
  flex-direction: column;
}

.page-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.5rem;
  background: oklch(0.46 0.055 260);
  color: oklch(0.89 0.006 260);
  font-size: 0.875rem;
}

.footer-left,
.footer-center,
.footer-right {
  flex: 1;
}

.footer-center {
  text-align: center;
}

.footer-right {
  text-align: right;
}

.page-footer a {
  color: oklch(0.89 0.006 260);
  text-decoration: underline;
}

.page-footer a:hover {
  color: #fff;
}

.site-content a:link {
  color: oklch(0.52 0.18 250);
  text-decoration: underline;
}

.site-content a:visited {
  color: oklch(0.44 0.18 300);
}

.stealth-link:visited {
  color: inherit;
}

/* Storybook styles */
.storybook-layout {
  display: flex;
  min-height: 100vh;
}

.story-sidebar {
  flex: 0 0 250px;
  background-color: oklch(0.98 0.003 260);
  padding: 1rem;
  border-right: 1px solid oklch(0.93 0.005 260);
  min-height: 100vh;
}

.story-main {
  flex: 1;
  min-width: 0;
}

.story-sidebar h3 {
  margin-top: 0;
  color: oklch(0.42 0.008 260);
}

/* The project sidebar's heading carries the navbar pin toggle, pushed to the
   right edge of the sidebar. */
.project-sidebar-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.navbar-pin-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border-radius: 50%;
  border: 1px solid transparent;
  background: none;
  font-size: 0.8rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0.35;
  filter: grayscale(100%);
}

.navbar-pin-toggle:hover {
  opacity: 0.75;
  border-color: oklch(0.75 0.01 260);
  background-color: oklch(0.93 0.005 260);
}

.navbar-pin-toggle.pinned {
  opacity: 1;
  filter: none;
  border-color: oklch(0.75 0.01 260);
  background-color: oklch(0.93 0.005 260);
}

.navbar-pin-message {
  color: oklch(0.42 0.008 260);
  font-size: 0.8rem;
}

.navbar-pin-message:empty {
  display: none;
}

.story-nav-link {
  color: oklch(0.58 0.22 250) !important;
  text-decoration: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  transition: background-color 0.2s;
}

.story-nav-link:hover {
  background-color: oklch(0.93 0.005 260);
}

.story-nav-link.active {
  background-color: oklch(0.58 0.22 250);
  color: white !important;
}

.story-content {
  padding: 2rem;
}

.story-page h1 {
  margin-bottom: 1rem;
  border-bottom: 2px solid oklch(0.93 0.005 260);
  padding-bottom: 0.5rem;
}

.story-section {
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.story-section:last-child {
  border-bottom: none;
}

.color-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 0.75rem;
}

.color-swatch {
  width: 100px;
  height: 100px;
  border-radius: 6px;
  border: 1px solid oklch(0.89 0.006 260);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 6px 8px;
  font-family: var(--font-monospace);
  line-height: 1.3;
}

.color-swatch-name {
  font-size: 11px;
  font-weight: 700;
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fg-bg-grid {
  overflow-x: auto;
  margin-top: 0.75rem;
}

.fg-bg-header {
  display: flex;
  gap: 2px;
  margin-bottom: 2px;
}

.fg-bg-corner {
  width: 90px;
  min-width: 90px;
  font-size: 11px;
  color: oklch(0.63 0.012 260);
  display: flex;
  align-items: flex-end;
  padding-bottom: 4px;
  font-family: var(--font-monospace);
}

.fg-bg-col-label {
  width: 64px;
  min-width: 64px;
  height: 28px;
  font-size: 9px;
  font-family: var(--font-monospace);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 3px;
  border: 1px solid oklch(0.89 0.006 260);
  text-align: center;
  overflow: hidden;
}

.fg-bg-row {
  display: flex;
  gap: 2px;
  margin-bottom: 2px;
}

.fg-bg-row-label {
  width: 90px;
  min-width: 90px;
  font-size: 11px;
  font-family: var(--font-monospace);
  font-weight: 700;
  display: flex;
  align-items: center;
}

.fg-bg-cell {
  width: 64px;
  min-width: 64px;
  height: 32px;
  font-size: 14px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 3px;
  border: 1px solid oklch(0.89 0.006 260);
}

.color-elements-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin-top: 0.75rem;
}

.color-element-group h3 {
  margin-top: 0;
  margin-bottom: 0.5rem;
  font-size: 0.95rem;
  color: oklch(0.42 0.008 260);
}

.color-button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.color-badge-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.color-banners-demo {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

.color-tags-demo h3 {
  margin-top: 1rem;
  margin-bottom: 0.5rem;
  font-size: 0.95rem;
  color: oklch(0.42 0.008 260);
}

.color-tags-demo h3:first-child {
  margin-top: 0;
}

.color-input-demos {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.color-input-demos label {
  font-size: 0.85rem;
  color: oklch(0.55 0.01 260);
  display: block;
  margin-bottom: 2px;
}

.font-showcase {
  margin: 1rem 0;
  padding: 1rem;
  background-color: oklch(0.98 0.003 260);
  border-radius: 4px;
  border: 1px solid oklch(0.93 0.005 260);
}

.font-showcase h3 {
  margin-top: 0;
  color: oklch(0.42 0.008 260);
}

.font-showcase p {
  margin: 0.5rem 0;
}

.markdown-content {
  background-color: oklch(0.98 0.003 260);
  padding: 2rem;
  border-radius: 4px;
  border: 1px solid oklch(0.93 0.005 260);
}

.markdown-content code {
  background-color: oklch(0.93 0.005 260);
  padding: 0.2rem 0.4rem;
  border-radius: 3px;
  font-size: 0.9em;
}

.markdown-content pre {
  background-color: oklch(0.93 0.005 260);
  padding: 1rem;
  border-radius: 4px;
  overflow-x: auto;
}

.markdown-content pre code {
  background-color: transparent;
  padding: 0;
}

.markdown-content blockquote {
  border-left: 4px solid oklch(0.58 0.22 250);
  padding-left: 1rem;
  margin: 1rem 0;
  font-style: italic;
  color: oklch(0.55 0.01 260);
}

/* Error page styles */
.error-page-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 2rem;
}

.error-page {
  text-align: center;
  max-width: 700px;
  position: relative;
}

.error-code {
  font-family: var(--font-serif);
  font-size: 10rem;
  font-weight: 700;
  line-height: 1;
  color: oklch(0.85 0.008 260);
  transform: rotate(-25deg);
  user-select: none;
  position: absolute;
  top: -6rem;
  left: 50%;
  margin-left: -8rem;
  z-index: 0;
}

.error-emoji {
  font-family: var(--font-serif);
  font-size: 3rem;
  font-weight: 500;
  line-height: 1;
  color: oklch(0.85 0.008 260);
  transform: rotate(10deg);
  user-select: none;
  position: absolute;
  top: -7rem;
  left: 20%;
  margin-left: 13rem;
  z-index: 0;
}

.error-page h1 {
  margin-top: 0;
  margin-bottom: 1rem;
  position: relative;
  z-index: 1;
}

.error-page p {
  color: oklch(0.55 0.01 260);
  margin-bottom: 0.5rem;
  position: relative;
  z-index: 1;
}

.error-page .hint {
  font-size: 0.9rem;
  color: oklch(0.75 0.01 260);
}

/* Form validation styles */
.form-field {
  margin-bottom: 1rem;
}

/* A label that starts a new setting inside a run of stacked fields. Pure gives
   every stacked label margin: .25em 0, which is enough between an input and its
   own label but too little between one setting and the next.

   0.875rem is one `.hint` paragraph's bottom margin, so this is the answer to
   "can a margin be conditional": adjacent vertical margins collapse to the
   larger of the two, never the sum. After a hint the two 0.875rem margins
   collapse into one; after a bare select the label's own margin supplies the
   same gap. The spacing is identical either way with no selector doing the
   choosing. (Collapsing needs normal flow -- inside a flex or grid container
   the margins would add up instead, so use `gap` there.)

   Qualified with `label` to match the specificity of Pure's own
   `.pure-form-stacked label`; application.css loads after pure-min.css, so the
   tie goes to this rule. A bare `.setting-label` loses to Pure and does
   nothing. */
label.setting-label {
  margin-top: 0.875rem;
}

.field-error input,
.field-error select,
.field-error textarea {
  border-color: oklch(0.58 0.2 25);
  border-width: 2px;
  background-color: oklch(0.97 0.012 25);
}

.field-error label {
  color: oklch(0.58 0.2 25);
}

.validation-error-text,
.error-message {
  color: oklch(0.58 0.2 25);
  font-size: 0.875rem;
  margin-top: 0.25rem;
  display: block;
}

.validation-error-text:empty {
  display: none;
}

.form-error {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border: 1px solid transparent;
  font-size: 0.9rem;
  border-radius: 4px;
  padding: 0.75rem 1rem;
  background-color: oklch(0.97 0.012 25);
  border-color: oklch(0.58 0.2 25);
  color: oklch(0.58 0.2 25);
}

/* Helper text under a form field (e.g. why a field is locked) */
.form-help {
  color: oklch(0.55 0.01 260);
  font-size: 0.875rem;
  margin-top: 0.25rem;
  display: block;
}

/* Badge marking a protected system property (shown instead of a Delete button) */
.system-badge {
  border-radius: 8px;
  display: inline-block;
  padding: 0.15rem 0.5rem;
  font-size: 0.75rem;
  font-weight: bold;
  color: oklch(0.42 0.008 260);
  background-color: oklch(0.93 0.005 260);
  border: 1px solid oklch(0.85 0.008 260);
}

/* Radio button group */
.radio-group {
  display: flex;
  gap: 1.5rem;
  margin-top: 0.5rem;
}

.radio-label {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  cursor: pointer;
  font-weight: normal;
}

.radio-label input[type=radio] {
  margin: 0;
}

/* Form buttons */
.form-buttons {
  margin-top: 1.5rem;
  display: flex;
  gap: 0.5rem;
}

/* Button variants */
.button-success {
  background-color: oklch(0.62 0.16 145);
  color: white;
}

.button-success:hover {
  background-color: oklch(0.68 0.15 145);
}

.button-warning {
  background-color: oklch(0.58 0.2 25);
  color: white;
}

.button-warning:hover {
  background-color: oklch(0.58 0.2 25);
}

.warning-text {
  color: oklch(0.58 0.2 25);
  font-weight: 500;
}

.pure-button-small {
  font-size: 0.8rem;
  padding: 0.25rem 0.5rem;
}

/* =============================================================================
   Global Loading Overlay
   ============================================================================= */
#global-loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.8);
  display: none;
  justify-content: center;
  align-items: center;
  z-index: 2000;
  font-size: 1.25rem;
  color: oklch(0.3 0.006 260);
}

#global-loading-overlay.visible {
  display: flex;
}

/* Modal styles */
.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  border-radius: 8px;
  background-color: white;
  padding: 2rem;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  max-width: 500px;
  width: 90%;
}

.modal-content h2 {
  margin-top: 0;
  margin-bottom: 1rem;
}

.modal-content p {
  margin-bottom: 1rem;
  color: oklch(0.42 0.008 260);
}

.modal-buttons {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin-top: 1.5rem;
}

/* =============================================================================
   Share Modal
   ============================================================================= */
.share-modal {
  width: 90%;
  height: 90vh;
  max-width: none;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.share-modal-content {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.share-modal-table-container {
  flex: 1;
  overflow-y: auto;
  margin-bottom: 1rem;
  min-height: 0;
}

.share-modal-table {
  width: 100%;
}

.share-modal-table th {
  text-align: left;
  font-weight: 600;
  padding: 0.5rem;
  border-bottom: 2px solid oklch(0.85 0.008 260);
}

.share-modal-table td {
  padding: 0.5rem;
  vertical-align: middle;
}

.share-modal-row {
  transition: background-color 0.2s ease;
}

.share-modal-row.changed {
  background-color: oklch(0.97 0.055 92);
}

.share-modal-row.removed {
  background-color: oklch(0.9 0.045 20);
  text-decoration: line-through;
  color: oklch(0.55 0.01 260);
}

.share-modal-row.removed td {
  color: oklch(0.55 0.01 260);
}

.share-modal-user {
  line-height: 1.3;
}

.share-modal-user-name {
  font-weight: 500;
}

.share-modal-user-email {
  display: block;
  color: oklch(0.55 0.01 260);
  font-size: 0.875rem;
}

.share-modal-you {
  color: oklch(0.52 0.2 258);
  font-size: 0.875rem;
  font-style: italic;
}

.share-modal-role-select {
  padding: 0.25rem 0.5rem;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  font-size: 0.875rem;
  background-color: white;
}

.share-modal-role-text {
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  font-size: 0.875rem;
}

.share-modal-role-text.role-owner {
  background-color: oklch(0.92 0.045 145);
  color: oklch(0.35 0.1 145);
}

.share-modal-role-text.role-editor {
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.37 0.15 258);
}

.share-modal-role-text.role-viewer {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.share-modal-role-removed {
  color: oklch(0.58 0.2 25);
  font-style: italic;
}

.share-modal-actions {
  white-space: nowrap;
}

.share-modal-remove {
  background-color: #fff;
  border-color: oklch(0.58 0.2 25);
  color: oklch(0.58 0.2 25);
}

.share-modal-remove:hover {
  background-color: oklch(0.58 0.2 25);
  color: #fff;
}

.share-modal-undo {
  background-color: #fff;
  border-color: oklch(0.55 0.01 260);
  color: oklch(0.55 0.01 260);
}

.share-modal-undo:hover {
  background-color: oklch(0.55 0.01 260);
  color: #fff;
}

.share-modal-error {
  background-color: oklch(0.9 0.045 20);
  color: oklch(0.32 0.12 22);
  padding: 0.75rem 1rem;
  border-radius: 4px;
  margin-bottom: 1rem;
}

/* Share modal - pending addition row */
.share-modal-row.pending-add {
  background-color: oklch(0.92 0.045 145);
}

/* Share modal - search section */
.share-modal-search {
  max-width: 300px;
  margin-bottom: 0.5rem;
}

.share-modal-divider {
  border: none;
  border-top: 1px solid oklch(0.89 0.006 260);
  margin: 0.5rem 0 1rem 0;
  width: 100%;
}

/* Share modal - private checkbox section */
.share-modal-private-section {
  margin-bottom: 1em;
}

.share-modal-private-label {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-weight: 500;
  cursor: pointer;
}

.share-modal-private-subtitle {
  font-size: 0.85em;
  color: var(--text-muted, oklch(0.55 0.01 260));
  margin-top: 0.25em;
  margin-left: 1.5em;
}

.share-modal-search-label {
  font-weight: 500;
  margin-bottom: 0.5rem;
  display: block;
}

.share-modal-search-container {
  position: relative;
}

.share-modal-search-input {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  font-size: 0.875rem;
  box-sizing: border-box;
}

.share-modal-search-input:focus {
  outline: none;
  border-color: oklch(0.87 0.06 245);
  box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
}

.share-modal-search-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  background-color: white;
  border: 1px solid oklch(0.85 0.008 260);
  border-top: none;
  border-radius: 0 0 4px 4px;
  max-height: 200px;
  overflow-y: auto;
  z-index: 100;
  display: none;
}

.share-modal-search-dropdown.visible {
  display: block;
}

.share-modal-search-option {
  display: flex;
  flex-direction: column;
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  border: none;
  background: none;
  width: 100%;
  text-align: left;
}

.share-modal-search-option.highlighted {
  background-color: oklch(0.93 0.005 260);
}

.share-modal-search-option:hover {
  background-color: oklch(0.98 0.003 260);
}

.share-modal-search-option-name {
  font-weight: 500;
}

.share-modal-search-option-email {
  font-size: 0.8rem;
  color: oklch(0.55 0.01 260);
}

.share-modal-search-no-results {
  padding: 0.5rem 0.75rem;
  color: oklch(0.55 0.01 260);
  font-style: italic;
}

.share-modal-search-loading {
  padding: 0.5rem 0.75rem;
  color: oklch(0.55 0.01 260);
}

/* Server info styles */
.server-info {
  display: flex;
  gap: 2rem;
  flex-wrap: wrap;
}

.server-info-item {
  flex: 1;
  min-width: 200px;
  padding: 1rem;
  border-radius: 8px;
  background-color: oklch(0.98 0.003 260);
}

.server-info-item h2 {
  margin-top: 0;
  margin-bottom: 0.5rem;
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: oklch(0.55 0.01 260);
}

.server-info-value {
  font-size: 1.5rem;
  font-weight: 600;
  margin: 0;
  color: oklch(0.24 0.006 260);
}

.server-info-item.env-production {
  background-color: oklch(0.97 0.012 25);
  border: 1px solid oklch(0.9 0.045 20);
}

.server-info-item.env-production .server-info-value {
  color: oklch(0.32 0.12 22);
}

/* Application styles */
.room {
  padding: 5px 5px;
}

/* =============================================================================
   Dropdown Menu Component
   ============================================================================= */
.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-trigger {
  cursor: pointer;
}

.dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 100;
  min-width: 160px;
  padding: 0.5rem 0;
  margin: 0.25rem 0 0 0;
  background-color: white;
  border: 1px solid oklch(0.93 0.005 260);
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  list-style: none;
}

.dropdown-menu.open {
  display: block;
}

.dropdown-menu.dropdown-right {
  left: auto;
  right: 0;
}

.dropdown-menu.dropdown-above {
  top: auto;
  bottom: 100%;
  margin: 0 0 0.25rem 0;
}

.dropdown-item {
  display: block;
  width: 100%;
  padding: 0.5rem 1rem;
  color: oklch(0.24 0.006 260);
  text-decoration: none;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  font-size: 0.9rem;
}

.dropdown-item:hover {
  background-color: oklch(0.98 0.003 260);
}

.dropdown-item.dropdown-item-danger {
  color: oklch(0.58 0.2 25);
}

.dropdown-item.dropdown-item-danger:hover {
  background-color: oklch(0.97 0.012 25);
}

.dropdown-divider {
  height: 0;
  margin: 0.5rem 0;
  border-top: 1px solid oklch(0.93 0.005 260);
}

/* Disabled dropdown items */
.dropdown-item.disabled {
  color: oklch(0.75 0.01 260);
  cursor: not-allowed;
  pointer-events: none;
}

.dropdown-item.disabled:hover {
  background-color: transparent;
}

/* Dropdown item with label and shortcut */
.dropdown-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.5rem;
}

.dropdown-item-label {
  flex: 1;
}

.dropdown-item-shortcut {
  font-size: 0.75rem;
  color: oklch(0.55 0.01 260);
  text-align: right;
  white-space: nowrap;
}

.dropdown-item.disabled .dropdown-item-shortcut {
  color: oklch(0.85 0.008 260);
}

/* =============================================================================
   Editable Title Component
   ============================================================================= */
.editable-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.editable-title-display {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  padding: 0.15rem 0.35rem;
  border-radius: 4px;
  transition: background-color 120ms ease;
}

.editable-title-display:hover {
  background-color: oklch(0.98 0.003 260);
}

.editable-title-text {
  margin: 0;
}

.editable-title-btn {
  padding: 0.25rem 0.5rem;
  font-size: 0.75rem;
  background: none;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  cursor: pointer;
  color: oklch(0.55 0.01 260);
  line-height: 1;
}

.editable-title-btn:hover {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.editable-title-editor {
  display: none;
  align-items: center;
  gap: 0.5rem;
}

/* Data-attribute based editing state */
.editable-title[data-editing=true] .editable-title-display {
  display: none;
}

.editable-title[data-editing=true] .editable-title-editor {
  display: flex;
}

/* An h3-level title edits at h3 size; the h1 default would jump the layout
   the moment a group name went into edit mode. */
.editable-title-h3 .editable-title-input {
  font-size: 1.05rem;
  font-weight: 600;
}

.editable-title-h3 .editable-title-btn {
  font-size: 0.7rem;
  padding: 0.15rem 0.35rem;
}

.editable-title-input {
  font-family: var(--font-serif);
  font-size: 2rem;
  font-weight: 700;
  padding: 0.25rem 0.5rem;
  border: 2px solid oklch(0.58 0.22 250);
  border-radius: 4px;
  outline: none;
  min-width: 200px;
}

.editable-title-actions {
  display: flex;
  gap: 0.25rem;
}

.editable-title-save,
.editable-title-cancel {
  padding: 0.5rem;
  font-size: 1rem;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  line-height: 1;
}

.editable-title-save {
  background-color: oklch(0.62 0.16 145);
  color: white;
}

.editable-title-save:hover {
  background-color: oklch(0.62 0.16 145);
}

.editable-title-cancel {
  background-color: oklch(0.55 0.01 260);
  color: white;
}

.editable-title-cancel:hover {
  background-color: oklch(0.55 0.01 260);
}

/* =============================================================================
   Ordered Multi-Select Component
   ============================================================================= */
.multi-select {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.multi-select-selected {
  display: flex;
  gap: 0.25rem;
  flex-wrap: wrap;
}

.multi-select-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0.5rem;
  background-color: oklch(0.37 0.15 258);
  color: white;
  font-size: 0.8rem;
  border-radius: 12px;
}

.multi-select-chip .chip-remove {
  background: none;
  border: none;
  color: white;
  cursor: pointer;
  padding: 0;
  font-size: 1rem;
  line-height: 1;
  opacity: 0.8;
}

.multi-select-chip .chip-remove:hover {
  opacity: 1;
}

.multi-select-dropdown {
  position: relative;
  display: inline-block;
}

.multi-select-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.4rem 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: oklch(0.42 0.008 260);
  background-color: oklch(0.98 0.003 260);
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.15s ease;
}

.multi-select-trigger:hover {
  background-color: oklch(0.93 0.005 260);
  border-color: oklch(0.75 0.01 260);
}

.multi-select-trigger .dropdown-arrow {
  font-size: 0.75rem;
  color: oklch(0.55 0.01 260);
}

.multi-select-option {
  display: block;
  width: 100%;
  padding: 0.5rem 1rem;
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
}

.multi-select-option:hover,
.multi-select-option-highlighted {
  background-color: oklch(0.98 0.003 260);
}

.multi-select-option-highlighted:hover {
  background-color: oklch(0.93 0.005 260);
}

.multi-select-option.selected,
.multi-select-option[data-selected=true] {
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.37 0.15 258);
}

/* =============================================================================
   Searchable Multi-Select Component
   ============================================================================= */
.searchable-multi-select {
  position: relative;
  display: inline-block;
  min-width: 250px;
}

.sms-input-area {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  padding: 0.4rem 0.6rem;
  min-height: 38px;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  background-color: #fff;
  cursor: text;
  outline: none;
}

.sms-input-area:focus {
  border-color: oklch(0.58 0.22 250);
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.1);
}

.sms-chips {
  display: contents;
}

.sms-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.4rem;
  background-color: oklch(0.7 0.15 244);
  color: white;
  font-size: 0.8rem;
  border-radius: 10px;
  white-space: nowrap;
}

/* A group chip, in the same purple as its dropdown option. */
.sms-chip-group {
  background-color: oklch(0.53 0.22 300);
}

.sms-chip-remove {
  background: none;
  border: none;
  color: inherit;
  cursor: pointer;
  padding: 0;
  font-size: 0.9rem;
  line-height: 1;
  opacity: 0.7;
  margin-left: 0.1rem;
}

.sms-chip-remove:hover {
  color: oklch(0.62 0.2 27);
  opacity: 1;
}

.sms-text-input {
  flex: 1;
  min-width: 60px;
  font-family: var(--font-sans-serif);
  font-size: 0.9rem;
  white-space: nowrap;
}

.sms-placeholder {
  color: oklch(0.55 0.01 260);
  pointer-events: none;
}

.sms-cursor {
  display: inline-block;
  width: 1px;
  height: 1em;
  background-color: #000;
  vertical-align: text-bottom;
  margin-left: -0.5px;
  margin-right: -0.5px;
}

.sms-cursor.blink {
  animation: sms-cursor-blink 1s step-end infinite;
}

@keyframes sms-cursor-blink {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
.sms-selection {
  background-color: oklch(0.87 0.06 245);
}

.sms-input-area:not(:focus) .sms-selection {
  background-color: oklch(0.85 0.008 260);
}

/* Dropdown list */
.sms-dropdown-list {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 100;
  max-height: 250px;
  overflow-y: auto;
  padding: 0.25rem 0;
  margin: 0.25rem 0 0 0;
  background-color: white;
  border: 1px solid oklch(0.93 0.005 260);
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  list-style: none;
}

.searchable-multi-select[data-open=true] .sms-dropdown-list {
  display: block;
}

.sms-option {
  display: block;
  width: 100%;
  padding: 0.5rem 0.75rem;
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.9rem;
}

.sms-option:hover {
  background-color: oklch(0.98 0.003 260);
}

.sms-option-highlighted {
  background-color: oklch(0.93 0.005 260);
}

.sms-option-highlighted:hover {
  background-color: oklch(0.89 0.006 260);
}

/* A group option names several people at once. Purple separates it from a
   person without a label prefix, which would leak into search ranking. */
/* The group chips on a People-page row. The row is a flex line: name and
   meta on the left, groups filling the space before the invitee actions. */
/* The group column on a People row.
   `flex-grow: 0` is what makes the list read as a table: the row's link grows
   instead, so the column's left edge lands in the same place whatever the
   name's width. It still shrinks on a narrow viewport. The right padding
   matches `.user-link`'s, so the chips sit flush inside the row's own inset. */
.person-groups {
  flex: 0 1 16rem;
  min-width: 0;
  padding-right: 0.5rem;
}

.person-groups-static {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  align-items: center;
}

.person-group-name {
  padding: 0.15rem 0.4rem;
  background-color: oklch(0.53 0.22 300);
  color: white;
  font-size: 0.8rem;
  border-radius: 10px;
  white-space: nowrap;
}

.sms-option-group {
  color: oklch(0.53 0.22 300);
  font-weight: 500;
}

/* Freetext option styling - subtle emphasis to distinguish from regular options */
.sms-option-freetext {
  font-style: italic;
  color: oklch(0.42 0.008 260);
}

.sms-option[data-hidden=true] {
  display: none;
}

.sms-option[data-selected=true] {
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.37 0.15 258);
}

.sms-option-highlight {
  font-weight: 600;
  background-color: oklch(0.97 0.055 92);
}

.sms-no-results {
  padding: 0.5rem 0.75rem;
  color: oklch(0.55 0.01 260);
  font-style: italic;
  font-size: 0.9rem;
}

/* =============================================================================
   Document List (Finder-style)
   ============================================================================= */
.documents-page,
.projects-page {
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
  flex: 1;
  padding: 1rem 2rem;
  width: 100%;
  max-width: 120ch;
  margin: 0 auto;
}

.documents-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.documents-header h1 {
  margin: 0;
}

.documents-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
  padding: 0.75rem;
  background-color: oklch(0.98 0.003 260);
  border-radius: 4px;
}

.documents-controls input[type=text] {
  flex: 1;
  max-width: 300px;
  padding: 0.5rem 0.75rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
}

.documents-controls input[type=text]:disabled {
  background-color: oklch(0.93 0.005 260);
  cursor: not-allowed;
}

.document-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.document-row {
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.document-row:last-child {
  border-bottom: none;
}

/* Project rows in projects index - flex layout for left/right alignment */
.project-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-right: 0.5rem;
}

.project-row .document-link {
  flex: 1;
  min-width: 0;
}

.project-row .license-badge {
  flex-shrink: 0;
}

.project-row .document-updated {
  flex-shrink: 0;
  font-size: 0.85rem;
  color: oklch(0.55 0.01 260);
}

.document-link {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 0.5rem;
  color: inherit;
  text-decoration: none;
  transition: background-color 0.15s;
}

.document-link:hover {
  background-color: oklch(0.98 0.003 260);
}

.document-link:visited {
  color: inherit;
}

.document-icon {
  font-size: 1.5rem;
  flex-shrink: 0;
  width: 2rem;
  text-align: center;
}

.empty-document-icon {
  color: oklch(0.58 0.2 25);
  /* Red for empty documents */
  font-weight: bold;
}

.document-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.document-title-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.document-title-row .document-tags {
  flex-shrink: 0;
}

.document-title {
  font-weight: 600;
  font-size: 1rem;
  color: oklch(0.24 0.006 260);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.document-row.is-deleted .document-title {
  color: oklch(0.55 0.01 260);
  text-decoration: line-through;
}

.document-meta {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-size: 0.8rem;
  color: oklch(0.55 0.01 260);
}

.document-tags {
  display: flex;
  gap: 0.25rem;
}

.tag {
  border-radius: 8px;
  display: inline-block;
  padding: 0.15rem 0.5rem;
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
  font-size: 0.75rem;
}

.document-updated {
  white-space: nowrap;
}

.document-role {
  border-radius: 8px;
  padding: 0.15rem 0.5rem;
  background-color: oklch(0.92 0.045 145);
  color: oklch(0.35 0.1 145);
  font-size: 0.75rem;
}

.document-role.role-viewer {
  background-color: oklch(0.89 0.006 260);
  color: oklch(0.42 0.008 260);
}

.document-role.role-editor {
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.37 0.15 258);
}

.document-role.role-owner {
  background-color: oklch(0.92 0.045 145);
  color: oklch(0.35 0.1 145);
}

.documents-empty {
  text-align: center;
  padding: 3rem 1rem;
  color: oklch(0.55 0.01 260);
}

.documents-empty p {
  margin: 0.5rem 0;
}

/* =============================================================================
   Document View Page
   ============================================================================= */
.document-view {
  padding: 0;
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Directory view sits on the same content column as documents/projects/users
   so the gutter treatment is consistent across every listing page. */
.directory-view {
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
  flex: 1;
}

.document-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  background-color: #fff;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.document-toolbar .toolbar-left {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.document-toolbar .toolbar-right {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.85rem;
  color: oklch(0.55 0.01 260);
}

.document-toolbar .toolbar-right .document-type-badge {
  font-weight: 500;
  color: oklch(0.42 0.008 260);
}

.document-toolbar .dropdown-trigger {
  padding: 0.35rem 0.75rem;
  font-size: 0.875rem;
}

.document-header {
  padding: 1.5rem;
}

.document-breadcrumb {
  display: flex;
  align-items: center;
  font-size: 0.85rem;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.document-breadcrumb a {
  color: oklch(0.55 0.01 260);
  text-decoration: none;
}

.document-breadcrumb a:hover {
  color: oklch(0.42 0.008 260);
  text-decoration: underline;
}

.breadcrumb-icon {
  font-size: 0.8rem;
}

.breadcrumb-separator {
  color: oklch(0.75 0.01 260);
  margin: 0 0.1rem;
}

.document-header h1 {
  margin: 0;
}

/* Three-slot header row: breadcrumb left, title geometrically centered,
   tags/actions right. Grid keeps the center col in the true middle
   regardless of side widths. */
.document-header-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
}

.document-header-left {
  min-width: 0;
  overflow: hidden;
  justify-self: start;
}

.document-header-center {
  min-width: 0;
  justify-self: center;
}

.document-header-right {
  min-width: 0;
  justify-self: end;
}

/* Below 900px the tags slot wraps under the breadcrumb/title line. */
@media (max-width: 900px) {
  .document-header-row {
    grid-template-columns: 1fr auto;
  }
  .document-header-right {
    grid-column: 1/-1;
    justify-self: start;
    margin-top: 0.5rem;
  }
}
/* Below 600px stack all three: breadcrumb / title / tags in a single column. */
@media (max-width: 600px) {
  .document-header-row {
    grid-template-columns: 1fr;
  }
  .document-header-left,
.document-header-center,
.document-header-right {
    grid-column: 1/-1;
    justify-self: start;
  }
  .document-header-center {
    margin-top: 0.25rem;
  }
  .document-header-right {
    margin-top: 0.5rem;
  }
}
/* Directory-only action bar (contains the "New" dropdown) sits below the header row. */
.directory-actions {
  margin-top: 0.75rem;
  display: flex;
  justify-content: flex-end;
}

.document-meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.875rem;
  color: oklch(0.55 0.01 260);
}

.document-tags {
  margin-top: 0.75rem;
}

/* Document tags editor - compact variant for inline editing */
.document-tags-editor {
  margin-top: 0.5rem;
}

/* When the tags editor lives in the right slot of .document-header-row,
   it aligns inline with the title instead of stacking below the header. */
.document-header-right .document-tags-editor {
  margin-top: 0;
}

.document-tags-editor .searchable-multi-select {
  font-size: 0.85rem;
}

.document-tags-editor .sms-input-area {
  min-height: 2rem;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
}

.document-tags-editor .sms-chip {
  padding: 0.1rem 0.4rem;
  font-size: 0.75rem;
  border-radius: 10px;
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.document-tags-editor .sms-chip-remove {
  font-size: 0.7rem;
  margin-left: 0.25rem;
  padding: 0 0.15rem;
}

.document-tags-editor .sms-text-input {
  font-size: 0.85rem;
}

.document-tags-editor .sms-placeholder {
  font-size: 0.8rem;
}

.document-tags-editor .sms-dropdown-list {
  font-size: 0.85rem;
  max-height: 200px;
}

.document-tags-editor .sms-option {
  padding: 0.35rem 0.75rem;
}

.document-content {
  padding: 1.5rem;
}

.document-content .hint {
  color: oklch(0.55 0.01 260);
  font-style: italic;
}

/* Sheet document styles */
.sheet-document {
  width: 100%;
  max-width: 1400px;
}

.document-tab-layout {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  /* No horizontal padding at this level so the tabs, sheet-data-toolbar,
   and add-row-controls sit flush with the sheet-document edges.
   Children that need breathing room (banners, spreadsheet-container,
   sheet-models-page) apply their own horizontal padding/margin. */
  padding: 0;
}

/* Banners inside the sheet layout keep a horizontal inset so they don't
   look flush like the tab strip does. */
.sheet-layout > .app-banner {
  margin-left: 1rem;
  margin-right: 1rem;
}

/* A banner directly under the document toolbar takes the toolbar's own inset,
   so the two line up on the left edge of the content column. */
.document-view > .app-banner {
  margin-left: 1rem;
  margin-right: 1rem;
}

/* Page-level notice banners share one layout; color modifiers below set the
   palette per context. A banner is a flex row whose optional .banner-action
   button is pinned to the far right. */
.app-banner {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border: 1px solid transparent;
  font-size: 0.9rem;
  border-radius: 4px;
}

/* Inline banner button (e.g. "Return to current", "Update"); always right-aligned. */
.banner-action {
  border-radius: 4px;
  margin-left: auto;
  flex-shrink: 0;
  cursor: pointer;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  padding: 0.15rem 0.5rem;
  font: inherit;
}

.banner-action:hover {
  background: rgba(0, 0, 0, 0.06);
}

/* Warning palette: viewing a past Sheet revision (read-only). */
.sheet-revision-banner {
  background: var(--color-warning-bg, oklch(0.97 0.055 92));
  border-color: var(--color-warning-border, oklch(0.85 0.17 90));
}

/* Info palette: the settings page is open but read-only for this level. */
.settings-readonly-banner {
  background: oklch(0.96 0.02 250);
  border-color: oklch(0.87 0.06 245);
  color: oklch(0.52 0.2 258);
}

/* The settings form wraps its controls in a fieldset so one `disabled`
   attribute turns the whole page read-only. Strip the browser default box so
   the fieldset is invisible. */
.settings-fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

/* Grey palette: read-only presentations — the history lookback, the published
   view, and the email preview (layout from .app-banner). */
.history-view-banner,
.published-view-banner,
.email-view-banner {
  font-family: var(--font-sans-serif);
  background: oklch(0.93 0.005 260);
  border-color: oklch(0.75 0.01 260);
  color: oklch(0.42 0.008 260);
}

/* Info palette: a bound Sheet sitting behind its template's schema head. */
.sheet-template-stale-banner {
  background: oklch(0.96 0.02 250);
  border-color: oklch(0.87 0.06 245);
  color: oklch(0.52 0.2 258);
}

/* Warning palette: this page loaded an older build than the server now runs
   (see `staleBuild` in app.js). It takes the banner layout but not a banner's
   place in the document: app.js appends it to <body> from outside any page
   container, and a soft navigation replaces the content frame underneath it,
   so it is pinned to the viewport instead of flowing with the page. It sits
   below the modal backdrop (z-index 1000) — a notice must never cover a dialog
   the user is answering. */
.stale-build-banner {
  position: fixed;
  z-index: 900;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  max-width: min(36rem, 100vw - 2rem);
  margin: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  background: oklch(0.97 0.055 92);
  border-color: oklch(0.85 0.17 90);
  color: oklch(0.5 0.11 78);
}

.history-btn .history-summary {
  flex: 1;
}

.document-tab-nav {
  border-bottom: 2px solid oklch(0.93 0.005 260);
}

.document-tab-nav .pure-menu-list {
  display: flex;
  gap: 0;
}

.document-tab {
  padding: 0.75rem 1.5rem !important;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  color: oklch(0.42 0.008 260) !important;
  text-decoration: none;
}

.document-tab:hover {
  background-color: oklch(0.98 0.003 260);
  color: oklch(0.58 0.22 250) !important;
}

.document-tab.active {
  border-bottom-color: oklch(0.58 0.22 250);
  color: oklch(0.58 0.22 250) !important;
  font-weight: 500;
}

/* Collapsible tab bar: "Data" always shows; every other tab is .document-tab-extra
   and stays hidden until the chevron toggle is checked. Pure CSS via :has() — the
   checkbox holds the open/closed state, no JS. */
/* Specificity must beat pure-min's `.pure-menu-horizontal .pure-menu-item`
   (0,2,0), which otherwise forces these back to inline-block. */
.document-tab-nav .pure-menu-item.document-tab-extra {
  display: none;
}

.document-tab-nav:has(.document-tabs-toggle:checked) .pure-menu-item.document-tab-extra {
  display: inline-block;
}

.document-tabs-toggle-item {
  display: flex;
  align-items: center;
  /* Auto block margins center the toggle <li> vertically in the menu row
   (otherwise it sits at the top and the chevron looks high). */
  margin-top: auto;
  margin-bottom: auto;
}

/* The chevron is the checkbox itself (appearance stripped), so it stays keyboard-
   focusable and Space-togglable. Rotates › → ‹ with a transition between states. */
.document-tabs-toggle {
  appearance: none;
  -webkit-appearance: none;
  margin: 0 0.5rem;
  padding: 0;
  width: 1.75rem;
  height: 1.75rem;
  border: none;
  background: transparent;
  color: oklch(0.42 0.008 260);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
}

/* Chevron drawn from borders (not a glyph) so it sits perfectly centered in the
   flex-centered button — the › glyph rendered high in its line box. A small square
   with two borders rotates 45° → "›" (collapsed); +180° → "‹" (expanded). */
.document-tabs-toggle::before {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.2s ease;
  /* The bordered corner sits up-and-right; nudge so the chevron reads centered. */
  margin-left: -0.15rem;
}

.document-tabs-toggle:checked::before {
  transform: rotate(225deg);
  margin-left: 0;
  margin-right: -0.15rem;
}

.document-tabs-toggle:hover {
  background-color: oklch(0.98 0.003 260);
  color: oklch(0.58 0.22 250);
}

.document-tabs-toggle:focus-visible {
  outline: 2px solid oklch(0.58 0.22 250);
  outline-offset: 1px;
}

.document-tab-content {
  padding: 1rem 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  width: 100%;
}

/* =============================================================================
   Calendar document styles
   ============================================================================= */
.calendar-month-grid,
.calendar-week-grid,
.calendar-day-view {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  gap: 0.5rem;
}

@media (min-width: 601px) {
  .calendar-month-grid,
.calendar-week-grid,
.calendar-day-view {
    padding-left: 1rem;
    padding-right: 1rem;
  }
}
.calendar-month-header,
.calendar-week-header,
.calendar-day-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0;
}

.calendar-month-title,
.calendar-week-title,
.calendar-day-title {
  font-size: 1.1rem;
  font-weight: 500;
}

.calendar-nav-prev,
.calendar-nav-next {
  min-width: 2.5rem;
}

.calendar-header-title-group {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.calendar-nav-today {
  padding: 0.15rem 0.5rem;
  font-size: 0.8rem;
  line-height: 1.4;
}

.calendar-weekday-headers {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.calendar-weekday-header {
  text-align: center;
  font-weight: 500;
  font-size: 0.85rem;
  color: oklch(0.55 0.01 260);
  padding: 0.35rem 0;
}

.calendar-day-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  flex: 1;
  min-height: 0;
}

.calendar-day-cell {
  border: 1px solid oklch(0.93 0.005 260);
  padding: 0.25rem;
  min-height: 5rem;
  overflow: hidden;
}

.calendar-day-cell:hover {
  background-color: oklch(0.98 0.003 260);
}

.calendar-day-today {
  background-color: oklch(0.96 0.02 250);
}

.calendar-day-today .calendar-day-number,
.calendar-day-today .calendar-day-column-date {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.75em;
  height: 1.75em;
  padding: 0 0.35em;
  border-radius: 999px;
  background-color: oklch(0.58 0.2 25);
  color: #fff;
  line-height: 1;
  font-weight: 600;
}

.calendar-day-other-month {
  color: oklch(0.75 0.01 260);
  background-color: oklch(0.98 0.003 260);
}

.calendar-day-number {
  font-size: 0.85rem;
  font-weight: 500;
}

.calendar-day-open {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

.calendar-day-open:hover {
  color: inherit;
  text-decoration: underline;
}

.calendar-day-column-link,
.calendar-day-column-label {
  display: block;
}

.calendar-day-events {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 2px;
}

.calendar-event-marker {
  display: block;
  width: 100%;
  padding: 0.1rem 0.3rem;
  font-size: 0.78rem;
  line-height: 1.15;
  text-align: left;
  background: oklch(0.52 0.2 258);
  color: #fff;
  border: none;
  border-radius: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.calendar-event-marker:hover {
  opacity: 0.9;
}
.calendar-event-marker.is-continuation {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
.calendar-event-marker.is-continued {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.calendar-event-marker-week {
  position: absolute;
  --col: 0;
  --total: 1;
  left: calc(var(--col) / var(--total) * 100%);
  width: calc(1 / var(--total) * 100% - 2px);
  box-sizing: border-box;
  border: 1px solid oklch(0.37 0.15 258);
  top: calc(var(--start-pct, 0) * 1%);
  height: calc(var(--dur-pct, 4) * 1%);
  min-height: 1.2em;
  padding: 0.1rem 0.35rem;
  font-size: 0.75rem;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
  border-radius: 0;
}

.calendar-week-all-day {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 4px;
}

.calendar-event-marker-all-day {
  font-size: 0.72rem;
  background: oklch(0.52 0.2 258);
  color: #fff;
}

.calendar-day-columns {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  flex: 1;
  min-height: 0;
}

.calendar-day-columns-single {
  grid-template-columns: 1fr;
}

.calendar-day-column {
  border-left: 1px solid oklch(0.93 0.005 260);
  min-height: 20rem;
}

.calendar-day-column:first-child {
  border-left: none;
}

.calendar-day-column-header {
  text-align: center;
  font-weight: 500;
  font-size: 0.85rem;
  color: oklch(0.55 0.01 260);
  padding: 0.35rem 0;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.calendar-day-column-name {
  display: block;
  text-transform: uppercase;
  font-size: 0.7rem;
  letter-spacing: 0.05em;
}

.calendar-day-column-date {
  display: block;
  font-size: 1.1rem;
  font-weight: 600;
}

.calendar-hour-row {
  border-bottom: 1px solid oklch(0.96 0.004 260);
  height: 3rem;
  position: relative;
}

.calendar-hour-label {
  position: absolute;
  left: -3.5rem;
  top: -0.5em;
  font-size: 0.7rem;
  color: oklch(0.55 0.01 260);
  white-space: nowrap;
}

.calendar-hour-rows {
  position: relative;
}

.calendar-day-column:first-child .calendar-hour-rows {
  margin-left: 3.5rem;
}

.calendar-now-line {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--now-pct, 0) * 1%);
  height: 2px;
  background-color: oklch(0.58 0.2 25);
  z-index: 2;
  pointer-events: none;
}

.calendar-now-line::before {
  content: "";
  position: absolute;
  left: -4px;
  top: -3px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: oklch(0.58 0.2 25);
}

.calendar-event-block {
  position: absolute;
  left: 2px;
  right: 2px;
  background: #007bff;
  color: #fff;
  border-radius: 3px;
  padding: 0.15rem 0.3rem;
  font-size: 0.78rem;
  overflow: hidden;
  cursor: pointer;
}

.calendar-event-detail {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1rem 1rem;
}

.calendar-event-form {
  max-width: 600px;
}

.calendar-event-header {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 0.25rem;
}

.calendar-event-view {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.calendar-event-view-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.calendar-event-view-title {
  margin: 0;
  font-size: 1.5rem;
  flex: 1 1 auto;
  min-width: 0;
  word-break: break-word;
}

.calendar-event-view-time {
  margin: 0;
  color: oklch(0.55 0.01 260);
}

.calendar-event-view-label {
  font-weight: 600;
  color: oklch(0.55 0.01 260);
}

.section-subheading {
  margin: 0 0 0.5rem;
  font-size: 1rem;
  font-weight: 600;
  color: oklch(0.3 0.006 260);
}

.calendar-event-view-meta {
  margin-top: 1rem;
  padding-top: 0.5rem;
  border-top: 1px solid oklch(0.89 0.006 260);
  color: oklch(0.55 0.01 260);
  font-size: 0.875rem;
}

.calendar-event-view-repeats {
  margin: 0;
}

.calendar-event-view-description p,
.calendar-event-view-location p {
  margin: 0;
  white-space: pre-wrap;
}

.calendar-event-view-occurrence {
  margin: 0.25rem 0 0;
  font-style: italic;
}

.calendar-event-view-occurrence:first-child {
  margin-top: 0;
}

.calendar-event-view-cancelled {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border: 1px solid transparent;
  font-size: 0.9rem;
  border-radius: 4px;
  background: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.scope-modal .modal-buttons {
  flex-direction: column;
  align-items: stretch;
}

.scope-modal .calendar-scope-cancel {
  align-self: center;
  margin-top: 0.5rem;
}

.calendar-event-actions {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  padding-top: 0.75rem;
  border-top: 1px solid oklch(0.89 0.006 260);
  margin-top: 0.5rem;
}

.calendar-event-form[data-unedited=true] .calendar-event-header {
  display: none;
}

.calendar-event-menu-trigger {
  background: none;
  border: none;
  font-size: 1.25rem;
  line-height: 1;
  padding: 0.25rem 0.5rem;
  cursor: pointer;
  color: oklch(0.55 0.01 260);
  border-radius: 4px;
}
.calendar-event-menu-trigger:hover {
  background-color: oklch(0.89 0.006 260);
}

.calendar-event-field-group {
  margin-bottom: 0.75rem;
}
.calendar-event-field-group label {
  font-weight: 600;
  margin-bottom: 0.25rem;
  display: block;
}

.calendar-event-field-group .text-editor.mini-richtext-editor {
  width: 100%;
  box-sizing: border-box;
}

.calendar-event-description-readonly {
  white-space: pre-wrap;
  min-height: 5rem;
  padding: 0.5rem;
  font-size: 0.9rem;
  color: oklch(0.55 0.01 260);
  background-color: oklch(0.93 0.005 260);
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
}

.calendar-event-row {
  display: flex;
  gap: 1rem;
  align-items: flex-end;
}

.calendar-event-time-field {
  flex: 1;
}

.calendar-schedule-editor {
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  padding: 0.75rem;
}

.calendar-schedule {
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  padding: 0.75rem;
}
.calendar-schedule > label {
  font-weight: 600;
  margin-bottom: 0.25rem;
  display: block;
}

.schedule-until-group {
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid oklch(0.89 0.006 260);
}
.schedule-until-group input[type=date] {
  width: 12rem;
}

.schedule-editor-body {
  margin-top: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.schedule-editor-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
}
.schedule-editor-row > label {
  font-weight: 600;
  margin: 0;
}
.schedule-editor-row input[type=number] {
  width: 5rem;
}
.schedule-editor-row input[type=time] {
  width: 8rem;
}
.schedule-editor-row input[type=text] {
  flex: 1;
  min-width: 12rem;
}

.schedule-editor-row-stacked {
  flex-direction: column;
  align-items: stretch;
}
.schedule-editor-row-stacked > label {
  margin-bottom: 0.25rem;
}

.schedule-editor-hint {
  color: oklch(0.63 0.012 260);
  font-size: 0.85em;
  margin-top: 0.25rem;
}

.schedule-editor-choice-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.schedule-editor-choice-grid.dow-grid .schedule-editor-choice, .schedule-editor-choice-grid.weeks-grid .schedule-editor-choice {
  min-width: 3.5rem;
}
.schedule-editor-choice-grid.months-grid .schedule-editor-choice {
  min-width: 4rem;
}

label.schedule-editor-choice {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0.5rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  cursor: pointer;
}
label.schedule-editor-choice input[type=checkbox] {
  margin: 0;
}

.calendar-controls {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem 1rem 0;
}

.calendar-new-event {
  align-self: flex-start;
}

.calendar-agenda {
  display: none;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.5rem 0;
  overflow-y: auto;
  min-height: 0;
}

.calendar-agenda-empty {
  color: oklch(0.63 0.012 260);
  font-style: italic;
  padding: 1rem 0;
}

.calendar-agenda-day {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
}

.calendar-agenda-date {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 3rem;
  padding: 0.25rem 0.5rem;
  background: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
  border-radius: 4px;
  flex: 0 0 auto;
}

.calendar-agenda-weekday {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: oklch(0.55 0.01 260);
}

.calendar-agenda-daynum {
  font-size: 1.35rem;
  font-weight: 600;
  line-height: 1;
}

.calendar-agenda-month {
  font-size: 0.7rem;
  color: oklch(0.55 0.01 260);
}

.calendar-agenda-events {
  list-style: none;
  padding: 0;
  margin: 0;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.calendar-agenda-event {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  padding: 0.4rem 0.6rem;
  font-size: 0.9rem;
  white-space: normal;
  text-overflow: clip;
}

.calendar-agenda-time {
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
  opacity: 0.85;
}

.calendar-agenda-title {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

@media (max-width: 600px) {
  .calendar-month-grid > .calendar-weekday-headers,
.calendar-month-grid > .calendar-day-grid,
.calendar-week-grid > .calendar-day-columns {
    display: none;
  }
  .calendar-agenda {
    display: flex;
  }
  .calendar-month-header,
.calendar-week-header,
.calendar-day-header {
    flex-wrap: wrap;
    gap: 0.25rem 0.5rem;
  }
  .calendar-month-title,
.calendar-week-title,
.calendar-day-title {
    font-size: 1rem;
  }
}
.sheet-page {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  width: 100%;
}

/* Models page scrollable content. Horizontal inset is content-local: the
   sheet-layout no longer pads its children, so this and the Views/Forms
   pages each supply their own breathing room. The Data tab is the
   exception — it stays flush at this level and its spreadsheet-container
   supplies the inset separately. */
.sheet-models-page {
  overflow-y: auto;
  padding: 0 1.5rem 1.5rem 1.5rem;
}

/* Read-only schema view (viewing a past revision): show the models/fields but
   neutralize every editing affordance. Inputs read as plain text; drag handles,
   drop zones and menus are removed. */
.sheet-models-page.read-only input,
.sheet-models-page.read-only select,
.sheet-models-page.read-only textarea,
.sheet-models-page.read-only button,
.sheet-models-page.read-only .dropdown {
  pointer-events: none;
}

.sheet-models-page.read-only input,
.sheet-models-page.read-only select,
.sheet-models-page.read-only textarea {
  background: transparent;
  border-color: transparent;
  cursor: default;
}

.sheet-models-page.read-only .drag-handle,
.sheet-models-page.read-only .drop-zone,
.sheet-models-page.read-only .model-fields-actions {
  display: none;
}

/* Hide the model/field action menus (delete) but keep the parent-inheritance
   selector visible — it conveys schema info; it's made non-interactive above. */
.sheet-models-page.read-only .dropdown:not(.parent-selector) {
  display: none;
}

.sheet-page h2 {
  margin-top: 0;
  margin-bottom: 1rem;
  font-size: 1.5rem;
}

.sheet-page .hint {
  color: oklch(0.55 0.01 260);
  font-style: italic;
}

/* Models error message */
.models-error {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
  background-color: oklch(0.9 0.045 20);
  border: 1px solid oklch(0.9 0.045 20);
  border-radius: 4px;
  color: oklch(0.32 0.12 22);
}

.models-error-message {
  flex: 1;
}

.models-error-close {
  background: none;
  border: none;
  font-size: 1.25rem;
  color: oklch(0.32 0.12 22);
  cursor: pointer;
  padding: 0 0.25rem;
  line-height: 1;
  opacity: 0.7;
}

.models-error-close:hover {
  opacity: 1;
}

/* Models list container */
.models-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 100%;
}

.models-empty {
  padding: 2rem;
  text-align: center;
  background-color: oklch(0.98 0.003 260);
  border-radius: 8px;
}

.models-actions {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid oklch(0.93 0.005 260);
}

/* Model card */
.model-card {
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 8px;
  padding: 1rem;
  background-color: #fff;
  width: 100%;
  box-sizing: border-box;
}

.model-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.75rem;
}

.model-card-name {
  font-size: 1.1rem;
  font-weight: 500;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 0.25rem 0.5rem;
  background: transparent;
  flex: 1;
  margin-right: 0.5rem;
}

.model-card-name:hover {
  border-color: oklch(0.93 0.005 260);
  background-color: oklch(0.98 0.003 260);
}

.model-card-name:focus {
  outline: none;
  border-color: oklch(0.58 0.22 250);
  background-color: #fff;
}

/* Parent model selector */
.parent-selector {
  flex-shrink: 0;
  margin-right: 0.5rem;
}

.parent-selector-trigger {
  font-size: 0.85rem;
  padding: 0.25rem 0.5rem;
  color: oklch(0.55 0.01 260);
  background: transparent;
  border: 1px solid transparent;
}

.parent-selector-trigger:hover {
  background-color: oklch(0.98 0.003 260);
  border-color: oklch(0.93 0.005 260);
}

.parent-selector-menu {
  min-width: 200px;
  max-width: 280px;
  padding: 0.5rem;
}

.parent-selector-search {
  width: 100%;
  padding: 0.375rem 0.5rem;
  font-size: 0.875rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  margin-bottom: 0.5rem;
}

.parent-selector-search:focus {
  outline: none;
  border-color: oklch(0.58 0.22 250);
}

.parent-selector-options {
  max-height: 200px;
  overflow-y: auto;
}

.parent-selector-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.375rem 0.5rem;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.875rem;
}

.parent-selector-option:hover {
  background-color: oklch(0.98 0.003 260);
}

.parent-selector-option input[type=checkbox] {
  margin: 0;
}

.parent-option-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.parent-selector-empty {
  padding: 0.5rem;
  color: oklch(0.55 0.01 260);
  font-size: 0.875rem;
  font-style: italic;
  text-align: center;
}

/* Model fields list */
.model-fields-list {
  margin-top: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.model-fields-empty {
  margin: 0;
  padding: 0.5rem;
  color: oklch(0.55 0.01 260);
  font-size: 0.875rem;
}

.model-field-row {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.25rem;
  border-radius: 4px;
}

.model-field-row:hover {
  background-color: oklch(0.98 0.003 260);
}

/* Inherited fields section */
.inherited-fields-section {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding-bottom: 0.5rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px dashed oklch(0.89 0.006 260);
}

.own-fields-section {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* PersonalInfo group: a locked cluster of part columns (added/removed as a unit) */
.personal-info-group {
  margin-top: 0.5rem;
  padding: 0.5rem;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  background-color: oklch(0.98 0.003 260);
}

.personal-info-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.personal-info-group-title {
  font-weight: 600;
  color: oklch(0.55 0.01 260);
}

.personal-info-group-parts {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.model-field-row.personal-info-part {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  background-color: #ffffff;
  opacity: 0.95;
}

.add-personal-info-button {
  margin-left: 0.5rem;
}

/* Inherited (read-only) field row - stays horizontal */
.model-field-row.inherited-field {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  background-color: oklch(0.98 0.003 260);
  opacity: 0.8;
}

.model-field-row.inherited-field:hover {
  background-color: oklch(0.93 0.005 260);
}

.inherited-field-indicator {
  color: oklch(0.75 0.01 260);
  font-size: 0.875rem;
  width: 1.25rem;
  text-align: center;
  flex-shrink: 0;
}

.field-name-readonly {
  flex: 1;
  font-size: 0.875rem;
  color: oklch(0.42 0.008 260);
  padding: 0.375rem 0.5rem;
}

.field-kind-readonly {
  width: 120px;
  font-size: 0.875rem;
  color: oklch(0.55 0.01 260);
  padding: 0.375rem 0.5rem;
}

.inherited-from {
  font-size: 0.75rem;
  color: oklch(0.75 0.01 260);
  white-space: nowrap;
}

.field-name-input {
  flex: 1;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  padding: 0.375rem 0.5rem;
  font-size: 0.875rem;
}

.field-name-input:focus {
  outline: none;
  border-color: oklch(0.58 0.22 250);
}

.field-kind-select {
  width: 120px;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  padding: 0.375rem 0.5rem;
  font-size: 0.875rem;
  background-color: #fff;
}

.field-kind-select:focus {
  outline: none;
  border-color: oklch(0.58 0.22 250);
}

/* Model field row content wrapper */
.model-field-row-content {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
}

.model-field-row-content .field-name-input {
  flex: 1;
  min-width: 0;
}

.model-field-row-content .field-kind-select {
  flex-shrink: 0;
}

/* Options field variants editor */
.options-variants-editor {
  margin-left: 1.75rem;
  padding: 0.5rem;
  background-color: oklch(0.98 0.003 260);
  border: 1px solid oklch(0.93 0.005 260);
  border-radius: 4px;
}

.variant-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.375rem;
}

.variant-row:last-of-type {
  margin-bottom: 0;
}

.variant-input {
  flex: 1;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  padding: 0.25rem 0.5rem;
  font-size: 0.8125rem;
}

.variant-input:focus {
  outline: none;
  border-color: oklch(0.58 0.22 250);
}

.variant-remove-btn {
  padding: 0.125rem 0.5rem;
  font-size: 1rem;
  line-height: 1;
  color: oklch(0.58 0.2 25);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
}

.variant-remove-btn:hover {
  background-color: oklch(0.97 0.012 25);
  border-color: oklch(0.58 0.2 25);
}

.variant-add-btn {
  margin-top: 0.375rem;
  padding: 0.25rem 0.5rem;
  font-size: 0.8125rem;
  color: oklch(0.58 0.22 250);
  background: transparent;
  border: 1px dashed oklch(0.58 0.22 250);
  border-radius: 4px;
  cursor: pointer;
}

.variant-add-btn:hover {
  background-color: oklch(0.96 0.02 250);
}

/* Inherited field variants display */
.inherited-variants {
  font-style: italic;
  color: oklch(0.55 0.01 260);
}

/* Model field actions */
.model-fields-actions {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
}

.add-field-button {
  font-size: 0.875rem;
  padding: 0.25rem 0.75rem;
}

/* Small ellipsis menu button for models/fields */
.model-card-header .dropdown-trigger,
.model-field-row .dropdown-trigger {
  padding: 0.25rem 0.5rem;
  font-size: 1rem;
  color: oklch(0.55 0.01 260);
  background: transparent;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  line-height: 1;
}

.model-card-header .dropdown-trigger:hover,
.model-field-row .dropdown-trigger:hover {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.model-card-header .dropdown-trigger:focus-visible,
.model-field-row .dropdown-trigger:focus-visible {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
  outline: 2px solid oklch(0.58 0.22 250);
  outline-offset: 1px;
}

.document-access {
  padding: 1.5rem;
  border-top: 1px solid oklch(0.93 0.005 260);
}

.document-access h2 {
  margin-top: 0;
  font-size: 1.25rem;
}

/* Status badges */
.status-active {
  color: oklch(0.35 0.1 145);
}

.status-deleted {
  color: oklch(0.32 0.12 22);
}

/* Delete confirmation modal */
#delete-confirm-modal {
  display: none;
}

#delete-confirm-modal[data-visible=true] {
  display: flex;
}

#make-template-modal {
  display: none;
}

#make-template-modal[data-visible=true] {
  display: flex;
}

#make-template-modal .modal-content {
  max-width: 640px;
}

/* Superadmin permanent ("true") delete modal */
#hard-delete-modal {
  display: none;
}

#hard-delete-modal[data-visible=true] {
  display: flex;
}

.hard-delete-modal-content {
  max-width: 560px;
}

.hard-delete-effects {
  margin: 0 0 1rem 1.25rem;
  color: oklch(0.42 0.008 260);
}

.hard-delete-effects li {
  margin-bottom: 0.25rem;
}

.hard-delete-phrase {
  font-family: var(--font-monospace);
  font-weight: 700;
  background-color: oklch(0.93 0.005 260);
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
}

/* Phase 5c "advance to newest template" modal */
#sheet-ref-advance-modal {
  display: none;
}

#sheet-ref-advance-modal[data-visible=true] {
  display: flex;
}

.schema-advance-changes {
  margin: 0 0 1rem 1.25rem;
  color: oklch(0.42 0.008 260);
  max-height: 16rem;
  overflow-y: auto;
}

.schema-advance-changes li {
  margin-bottom: 0.25rem;
}

.schema-advance-hidden-note {
  color: oklch(0.42 0.008 260);
}

.schema-advance-unavailable {
  color: oklch(0.63 0.012 260);
}

.hard-delete-confirm-input {
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 0.5rem;
  font-family: var(--font-monospace);
}

/* Stronger red than .button-warning to mark an irreversible action. */
.button-danger {
  background-color: oklch(0.32 0.12 22);
  color: white;
}

.button-danger:hover {
  background-color: oklch(0.4 0.14 22);
}

.button-danger:disabled,
.button-danger[disabled] {
  background-color: oklch(0.9 0.045 20);
  color: #fff;
  cursor: not-allowed;
}

/* Project settings "Danger Zone" section */
.danger-zone {
  border-radius: 8px;
  border: 1px solid oklch(0.9 0.045 20);
  padding: 1rem;
  margin-top: 1.5rem;
  background-color: oklch(0.9 0.045 20);
}

.danger-zone h3 {
  color: oklch(0.32 0.12 22);
  margin-top: 0;
}

/* =============================================================================
   User Profile Pages
   ============================================================================= */
.users-page {
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
  flex: 1;
  width: 100%;
  max-width: 120ch;
  margin: 0 auto;
  padding: 1rem 2rem;
}

/* Open-sided list (matches .document-list). The column's own edges are
   drawn by content-column-edges on the page container; the list carries
   only the row separators. */
.user-list {
  list-style: none;
  padding: 0;
  margin: 1rem 0;
}

.user-item {
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.user-item:last-child {
  border-bottom: none;
}

.user-link {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 0.5rem;
  color: inherit;
  text-decoration: none;
  transition: background-color 0.15s;
}

.user-link:hover {
  background-color: oklch(0.98 0.003 260);
}

.user-link:visited {
  color: inherit;
}

.user-icon {
  font-size: 1.5rem;
  flex-shrink: 0;
  width: 2rem;
  text-align: center;
}

.user-info {
  flex: 1;
  min-width: 0;
}

.user-name {
  display: block;
  font-weight: 500;
  color: oklch(0.24 0.006 260);
}

.user-meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.8rem;
  color: oklch(0.55 0.01 260);
  margin-top: 0.25rem;
}

.user-email {
  color: oklch(0.55 0.01 260);
}

.user-private-tag {
  background-color: oklch(0.9 0.045 20);
  color: oklch(0.32 0.12 22);
  padding: 0.125rem 0.5rem;
  border-radius: 4px;
  font-size: 0.75rem;
}

.user-profile {
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
  flex: 1;
  /* Match documents/projects/users at 120ch so all listing/profile pages
   share the same column width. */
  width: 100%;
  max-width: 120ch;
  min-width: min(800px, 100%);
  margin: 0 auto;
  padding: 1rem;
}

.user-profile h1 {
  margin-bottom: 0.5rem;
}

.profile-status {
  margin-bottom: 1rem;
}

.status-public {
  border-radius: 8px;
  display: inline-block;
  padding: 0.25rem 0.5rem;
  background: oklch(0.92 0.045 145);
  color: oklch(0.35 0.1 145);
  font-size: 0.875rem;
}

.status-private {
  border-radius: 8px;
  display: inline-block;
  padding: 0.25rem 0.5rem;
  background: oklch(0.9 0.045 20);
  color: oklch(0.32 0.12 22);
  font-size: 0.875rem;
}

/* Administrative badge. The level modifier only changes the colour; see
   `common::superadmin::AdminLevel::css_class`. */
.status-superadmin {
  border-radius: 8px;
  display: inline-block;
  padding: 0.25rem 0.5rem;
  background: oklch(0.97 0.055 92);
  color: oklch(0.5 0.11 78);
  font-size: 0.875rem;
}

.status-admin-l1 {
  background: oklch(0.9 0.045 20);
  color: oklch(0.32 0.12 22);
}

.status-admin-l2 {
  background: oklch(0.97 0.055 92);
  color: oklch(0.5 0.11 78);
}

.status-admin-l3 {
  background: oklch(0.88 0.05 305);
  color: oklch(0.53 0.22 300);
}

.status-timezone {
  border-radius: 8px;
  display: inline-block;
  padding: 0.25rem 0.5rem;
  background: oklch(0.88 0.05 305);
  color: oklch(0.53 0.22 300);
  font-size: 0.875rem;
}

/* Honorific + pronouns subtitle under the profile name. */
.profile-identity-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
  color: oklch(0.55 0.01 260);
}

.profile-honorific {
  font-weight: 600;
}

.profile-pronouns {
  border-radius: 8px;
  display: inline-block;
  padding: 0.15rem 0.5rem;
  background: oklch(0.88 0.05 305);
  color: oklch(0.53 0.22 300);
  font-size: 0.85rem;
}

/* Bio rich-text block on the read-only profile. */
.profile-bio {
  margin-bottom: 1.5rem;
}

.profile-bio-content {
  line-height: 1.5;
  white-space: pre-wrap;
}

/* Amber palette: project license notice (layout from .app-banner). */
.project-license-banner {
  background: oklch(0.97 0.055 92);
  border-color: oklch(0.85 0.17 90);
  color: oklch(0.5 0.11 78);
}

/* Purple palette: project timezone notice (layout from .app-banner). */
.project-timezone-banner {
  background: oklch(0.88 0.05 305);
  border-color: oklch(0.53 0.22 300);
  color: oklch(0.53 0.22 300);
}

.profile-actions {
  margin-top: 1.5rem;
}

/* Admin Stats Section */
.admin-stats {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid oklch(0.93 0.005 260);
}

.admin-stats h2 {
  font-size: 1.25rem;
  margin-bottom: 1rem;
  color: oklch(0.42 0.008 260);
}

.stats-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.5rem 1rem;
  margin: 0;
}

.stats-list dt {
  font-weight: 500;
  color: oklch(0.55 0.01 260);
}

.stats-list dd {
  margin: 0;
  font-weight: 600;
  color: oklch(0.24 0.006 260);
}

.stats-list .ip-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.stats-list .ip-list li {
  margin: 0;
}

.stats-list .ip-list code {
  font-size: 0.85rem;
  background: oklch(0.93 0.005 260);
  padding: 0.15rem 0.4rem;
  border-radius: 3px;
}

.stats-list .honeypot-warning {
  color: oklch(0.5 0.11 78);
  background-color: oklch(0.97 0.055 92);
  padding: 0.15rem 0.4rem;
  border-radius: 3px;
}

.admin-stats h3 {
  margin-top: 1.5rem;
  margin-bottom: 0.75rem;
  font-size: 1.1rem;
  color: oklch(0.42 0.008 260);
  border-top: 1px solid oklch(0.89 0.006 260);
  padding-top: 1rem;
}

.edit-profile-page {
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
  flex: 1;
  /* Match documents/projects/users at 120ch so the edit-profile page
   shares the same column width as the other centered pages. */
  width: 100%;
  max-width: 120ch;
  min-width: min(800px, 100%);
  margin: 0 auto;
  padding: 1rem;
}

.edit-profile-page .hint {
  font-size: 0.875rem;
  color: oklch(0.55 0.01 260);
  margin-top: 0.25rem;
}

.edit-profile-page .form-buttons {
  margin-top: 1.5rem;
  display: flex;
  gap: 0.5rem;
}

/* Personal URL (slug) field with live availability check */
.personal-url-field {
  display: flex;
  align-items: center;
}

.personal-url-prefix {
  color: oklch(0.55 0.01 260);
  font-family: monospace;
  white-space: nowrap;
  margin-right: 0.25rem;
}

.personal-url-field input {
  flex: 1;
}

.url-status {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  min-height: 1.25em;
  color: oklch(0.55 0.01 260);
}

.url-status.is-available {
  color: oklch(0.52 0.2 258);
}

.url-status.is-taken {
  color: oklch(0.58 0.2 25);
}

.url-status.is-invalid {
  color: oklch(0.58 0.2 25);
}

.empty-state {
  color: oklch(0.55 0.01 260);
  font-style: italic;
  padding: 2rem;
  text-align: center;
}

/* =============================================================================
   Users Page Controls
   ============================================================================= */
.users-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.users-controls #users-search {
  flex: 1;
  min-width: 200px;
  max-width: 300px;
  padding: 0.5rem;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
}

.users-empty {
  padding: 2rem;
  text-align: center;
  color: oklch(0.55 0.01 260);
}

/* =============================================================================
   Pagination Controls
   ============================================================================= */
.pagination-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid oklch(0.93 0.005 260);
  flex-wrap: wrap;
}

.pagination-info {
  color: oklch(0.55 0.01 260);
  font-size: 0.875rem;
}

.pagination-pages {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.pagination-page {
  min-width: 2rem;
  height: 2rem;
  padding: 0 0.5rem;
  border: 1px solid oklch(0.85 0.008 260);
  background: #fff;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.875rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.pagination-page:hover:not(.active) {
  background: oklch(0.98 0.003 260);
  border-color: oklch(0.85 0.008 260);
}

.pagination-page.active {
  background: oklch(0.58 0.22 250);
  color: #fff;
  border-color: oklch(0.58 0.22 250);
  cursor: default;
}

.pagination-prev,
.pagination-next {
  font-weight: bold;
}

.pagination-ellipsis {
  padding: 0 0.5rem;
  color: oklch(0.75 0.01 260);
}

.per-page-selector {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.per-page-selector label {
  color: oklch(0.55 0.01 260);
  font-size: 0.875rem;
}

.per-page-select {
  padding: 0.25rem 0.5rem;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  font-size: 0.875rem;
}

/* =============================================================================
   Plaintext Document View
   ============================================================================= */
.plaintext-document {
  max-width: 1400px;
}

.document-type-badge {
  padding: 0.25rem 0.5rem;
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.37 0.15 258);
  font-size: 0.75rem;
  border-radius: 4px;
  margin-left: auto;
}

.plaintext-panels {
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
  flex: 1;
  /* Column-stack the notification banner + editor. Was `row + flex-wrap`
   which, once the mixin added `flex: 1` (so the panels reach the
   footer), let `align-content: stretch` distribute the tall row across
   the two wrapped rows — the notification blew up to ~300px because it
   claimed half of the extra vertical space. Column layout keeps the
   notification at content-height and lets the editor consume the rest. */
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1rem;
  min-height: 500px;
  width: 100%;
  max-width: 1000px;
  min-width: 600px;
  margin: 0 auto;
  box-sizing: border-box;
}

.plaintext-editor-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
}

/* Flex wrapper that places the panel flush-right alongside the document */
.document-with-panel {
  display: flex;
  align-items: stretch;
  min-height: calc(100vh - 60px);
}

.document-with-panel > .document-view {
  flex: 1;
  min-width: 0;
  max-width: none;
  margin: 0;
}

/* Project view - full width, no padding */
.project-view-fullwidth {
  max-width: none;
  margin: 0;
  padding: 0;
}

.project-view-fullwidth .storybook-layout {
  min-height: calc(100vh - 60px);
}

.project-view-fullwidth .story-main {
  flex: 1;
  min-width: 0;
  /* Flex column so .story-content inside can flex-grow to the full row
   height (matches the sidebar) instead of collapsing to content-height. */
  display: flex;
  flex-direction: column;
}

/* Project sidebar sits on the same white content surface as the story
   content column, with a soft edge on its left gutter side so nav +
   content read as two panels floating together over the gray-50 page.
   The right edge is where it meets .story-content — no gutter treatment
   there; the border-right + story-content's own left edge cover the seam.
   Also drop the sidebar's global 100vh floor (see prior fix) so the
   row's calc height governs. */
.project-view-fullwidth .story-sidebar {
  min-height: 0;
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
}

.project-view-fullwidth .story-content {
  background: #fff;
  box-shadow: -1px 0 0 oklch(0.93 0.005 260), 1px 0 0 oklch(0.93 0.005 260), 0 0 12px -2px rgba(0, 0, 0, 0.05);
  flex: 1;
  /* Guarantee 800px reading width when the viewport allows; below that
   the min collapses to 100% so the column shrinks with the viewport
   instead of forcing horizontal scroll. Can still expand up to
   1200px if the content pushes past 800. Gutters take whatever's
   left over. */
  min-width: min(800px, 100%);
  max-width: 1200px;
  margin: 0 auto;
  padding: 1rem;
}

/* Project home page header */
.project-home-header {
  margin-bottom: 1.5rem;
}

.project-home-header .editable-title {
  font-size: 1.75rem;
  font-weight: 600;
}

/* Widget grid, shared by Project home and the /app landing page. `auto-fit`
   collapses to one column when the viewport is narrower than 2 * 22rem + gap,
   so a page that emits a single column needs no special case here. */
.widget-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
  gap: 1.5rem;
  align-items: start;
}

/* One column of the grid. Deliberately not left/right — a customizable
   layout has no fixed sides. */
.widget-column {
  min-width: 0;
  /* Stack widgets vertically with breathing room between them; the grid
   `gap` only spaces the outer columns, not siblings inside one. */
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* Widget container — one outline per widget; content inside blends against
   the widget's background. */
.widget {
  background: oklch(0.98 0.003 260);
  padding: 1rem 1.25rem;
  border-radius: 8px;
  border: 1px solid oklch(0.89 0.006 260);
}

.widget-title {
  margin: 0 0 0.75rem;
  font-size: 1.1rem;
  font-weight: 600;
  color: oklch(0.3 0.006 260);
}

/* A heading inside a widget, one step below `.widget-title`. Used by My Next
   to separate "Now" from "Next" under one title. */
.widget-section-title {
  margin: 1rem 0 0.5rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: oklch(0.42 0.008 260);
}

.widget-section-title:first-of-type {
  margin-top: 0;
}

/* Only optional attendance is tagged. Required is what a listed meeting
   already implies, so it carries no badge. */
.my-next-attendance {
  font-style: italic;
  color: oklch(0.55 0.01 260);
}

/* Pin board widget: the project's chosen message-of-the-day document. The
   header carries the document title and, for an editor, the \2026 menu. */
.pin-board-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

/* The title already carries the widget's bottom margin, so clear it here and
   let the header own the spacing instead. */
.pin-board-header .widget-title {
  margin-bottom: 0;
  min-width: 0;
}

.pin-board-body,
.pin-board-hint {
  margin-top: 0.75rem;
}

.pin-board-hint,
.pin-board-empty {
  margin-bottom: 0;
  color: oklch(0.55 0.01 260);
}

/* Selector above, Pin button below, so a long document title never squeezes
   the button off the widget. */
.pin-board-picker-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
  margin-top: 0.75rem;
}

.pin-board-picker-form .searchable-multi-select {
  width: 100%;
}

/* ── Form embeds ───────────────────────────────────────────────────────────
   A display-only document inlined into a form section. Everything here is
   bounded by the form's own column: an embed must never widen the form or
   push it into horizontal scroll, whatever the source file's size. */
.form-embed {
  margin: 0 0 1rem;
  max-width: 100%;
}

.form-embed-image {
  display: block;
  /* The image scales down to the column and never up past its own size. */
  max-width: 100%;
  height: auto;
  border-radius: 4px;
}

.form-embed-frame {
  display: block;
  width: 100%;
  /* A tall PDF gets a readable page-shaped viewport that still fits a
   laptop screen; short viewports fall back to the vh cap. */
  aspect-ratio: 8.5/11;
  max-height: 70vh;
  border: 1px solid oklch(0.93 0.005 260);
  border-radius: 4px;
}

.form-embed-fallback {
  display: inline-block;
  margin-top: 0.25rem;
  font-size: 0.9rem;
}

.form-embed-caption {
  margin: 0.35rem 0 0;
  font-size: 0.9rem;
  color: oklch(0.55 0.01 260);
}

/* A long embedded document scrolls inside its own box rather than making the
   form endless. */
.form-embed-text {
  max-height: 24rem;
  overflow-y: auto;
  padding: 0.5rem 0.75rem;
  border: 1px solid oklch(0.93 0.005 260);
  border-radius: 4px;
}

/* Builder: the embed row reuses .builder-field's layout; these only add what
   is specific to an embed. */
.builder-embed-unresolved {
  margin: 0.25rem 0 0;
  color: oklch(0.5 0.11 78);
}

.builder-add-embed {
  margin-top: 1rem;
}

.builder-add-embed .searchable-multi-select {
  width: 100%;
}

.builder-embed-public-warning {
  margin: 0.5rem 0;
  color: oklch(0.5 0.11 78);
}

/* Home "Projects" widget: one link per project the user belongs to, with the
   same full-width hover row as the Upcoming cards. */
.home-projects-empty {
  margin: 0;
  color: oklch(0.55 0.01 260);
}

.home-projects-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.home-projects-item {
  display: block;
  margin: 0;
  border-top: 1px solid oklch(0.89 0.006 260);
}

.home-projects-item:first-child {
  border-top: none;
}

.home-project-card {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  /* Bleed to the widget's inner edges so the hover highlight spans the
   full inside width; matches `.widget`'s horizontal padding. */
  padding: 0.4rem 1.25rem;
  margin: 0 -1.25rem;
  text-decoration: none;
  color: oklch(0.24 0.006 260);
  background: transparent;
  transition: background-color 0.1s ease;
}

.home-project-card:hover {
  background: oklch(0.96 0.02 250);
}

.home-project-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Admin-stats widget: strip out the old `.admin-stats h2` heading margins
   and let the shared widget title carry the styling. */
.admin-stats-widget .stats-list {
  margin: 0;
}

/* Upcoming events widget: 3-line cards (meta / title / description) with
   dividers between rows and vertical margin so cards breathe. */
.upcoming-events-empty {
  margin: 0;
  color: oklch(0.55 0.01 260);
}

.upcoming-events-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.upcoming-event-item {
  display: block;
  margin: 0.5rem 0;
  border-top: 1px solid oklch(0.89 0.006 260);
  padding-top: 0.5rem;
}

.upcoming-event-item:first-child {
  margin-top: 0;
  border-top: none;
  padding-top: 0;
}

.upcoming-event-item:last-child {
  margin-bottom: 0;
}

.upcoming-event-card {
  display: block;
  /* Bleed to the widget's inner edges so the hover highlight spans the
   full inside width; matches `.widget`'s horizontal padding. */
  padding: 0.25rem 1.25rem;
  margin: 0 -1.25rem;
  text-decoration: none;
  color: oklch(0.24 0.006 260);
  background: transparent;
  transition: background-color 0.1s ease;
}

.upcoming-event-card:hover {
  background: oklch(0.96 0.02 250);
}

/* Meta row: date/time on the left, calendar tag pushed to the right. */
.upcoming-event-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: oklch(0.55 0.01 260);
  margin-bottom: 0.15rem;
}

.upcoming-event-when {
  color: oklch(0.42 0.008 260);
}

/* Calendar name is a subtle pill so it reads as a tag, not body text. */
.upcoming-event-calendar {
  padding: 0.05rem 0.4rem;
  background: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
  border-radius: 4px;
}

.upcoming-event-title {
  font-size: 1rem;
  font-weight: 500;
  margin-bottom: 0.15rem;
}

.upcoming-event-description {
  font-size: 0.9rem;
  color: oklch(0.42 0.008 260);
  line-height: 1.4;
}

/* Mini rich text rendered read-only. The canonical content string keeps one
   `\n` per visible line, and HTML collapses those to a space — every line of a
   description would run into the next without this. `pre-wrap` is safe because
   the markup carries no formatting whitespace of its own: it is emitted with no
   indentation and no newlines except the content's own. */
.richtext-content {
  white-space: pre-wrap;
}

/* Project people page - styled like users index */
.project-people-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.project-people-title-row h2 {
  margin: 0;
}

.project-people .users-controls {
  margin-bottom: 1.5rem;
}

/* Project Groups page: one heading per group over a short list of its people.
   The lists are the same open-sided rows the People page uses, so only the
   heading and the empty line are new here. */
.person-group-section {
  margin-bottom: 1.5rem;
}

/* The heading line: the group's name (editable in place for a manager) and
   its ⋯ menu at the far end. The rule under it is on the row, not the name,
   so it runs the width of the section whether or not there is a menu. */
.person-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding-bottom: 0.25rem;
  border-bottom: 1px solid oklch(0.89 0.006 260);
}

.person-group-header .editable-title-text {
  margin: 0;
  font-size: 1.05rem;
  color: oklch(0.24 0.006 260);
}

.person-group-menu {
  flex: 0 0 auto;
  padding-right: 0.5rem;
}

.person-group-menu .dropdown-trigger {
  background: none;
  border: none;
  box-shadow: none;
  font-size: 1.25rem;
  line-height: 1;
  padding: 0.25rem 0.4rem;
  cursor: pointer;
  color: oklch(0.55 0.01 260);
  border-radius: 4px;
}

.person-group-menu .dropdown-trigger:hover {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.3 0.006 260);
}

.person-group-section .user-list {
  margin: 0.25rem 0 0;
}

.person-group-empty {
  margin: 0.5rem 0 0;
  font-size: 0.9rem;
  color: oklch(0.55 0.01 260);
}

/* Document side panel (tabs + content) */
.document-side-panel {
  width: 320px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  border-left: 1px solid oklch(0.89 0.006 260);
  background-color: oklch(0.98 0.003 260);
}

#document-panel:empty {
  display: none;
}

.panel-tabs {
  display: flex;
  background-color: oklch(0.93 0.005 260);
  border-bottom: 1px solid oklch(0.89 0.006 260);
  overflow-x: auto;
  flex-shrink: 0;
}

.panel-tab {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.6rem;
  border-right: 1px solid oklch(0.89 0.006 260);
  background: transparent;
  font-size: 0.8rem;
  font-family: var(--font-sans-serif);
  color: oklch(0.42 0.008 260);
  white-space: nowrap;
}

.panel-tab.active {
  background-color: oklch(0.98 0.003 260);
  box-shadow: inset 0 -2px 0 oklch(0.58 0.22 250);
  color: oklch(0.24 0.006 260);
  font-weight: 600;
}

.panel-tab-label {
  cursor: pointer;
}

.panel-tab-label:hover {
  color: oklch(0.24 0.006 260);
}

.panel-tab-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 3px;
  font-size: 0.75rem;
  line-height: 1;
  color: oklch(0.63 0.012 260);
  cursor: pointer;
}

.panel-tab-close:hover {
  background-color: oklch(0.85 0.008 260);
  color: oklch(0.24 0.006 260);
}

.panel-content {
  flex: 1;
  padding: 0.75rem;
  overflow-y: auto;
}

.panel-content h3 {
  margin: 0 0 0.5rem 0;
  font-size: 0.95rem;
  font-family: var(--font-sans-serif);
  color: oklch(0.42 0.008 260);
}

/* Debug History panel */
.debug-history-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.debug-history-item {
  padding: 0.4rem 0;
  border-bottom: 1px solid oklch(0.93 0.005 260);
  font-size: 0.78rem;
  line-height: 1.4;
}

.debug-history-item:last-child {
  border-bottom: none;
}

.debug-history-item.skipped {
  opacity: 0.5;
}

.debug-history-user {
  font-weight: 600;
  color: oklch(0.24 0.006 260);
}

.debug-history-range {
  font-family: var(--font-monospace);
  font-size: 0.72rem;
  color: oklch(0.55 0.01 260);
  background-color: oklch(0.93 0.005 260);
  padding: 0.1rem 0.3rem;
  border-radius: 3px;
}

.debug-history-text {
  color: oklch(0.42 0.008 260);
  word-break: break-all;
}

.debug-history-gen {
  font-family: var(--font-monospace);
  font-size: 0.7rem;
  color: oklch(0.63 0.012 260);
}

.debug-history-skipped {
  font-size: 0.7rem;
  color: oklch(0.62 0.2 27);
  font-style: italic;
}

.debug-history-empty {
  color: oklch(0.55 0.01 260);
  font-style: italic;
  text-align: center;
  padding: 1rem 0;
}

/* Aggregated History panel */
.history-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.history-item {
  padding: 0;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.history-item:last-child {
  border-bottom: none;
}

.history-item.skipped {
  opacity: 0.5;
}

.history-user {
  font-weight: 600;
  font-size: 0.82rem;
  color: oklch(0.24 0.006 260);
}

.history-time {
  font-size: 0.72rem;
  color: oklch(0.63 0.012 260);
}

.history-skipped {
  color: oklch(0.62 0.2 27);
  font-style: italic;
}

.history-empty {
  color: oklch(0.55 0.01 260);
  font-style: italic;
  text-align: center;
  padding: 1rem 0;
}

/* History buttons */
.history-btn {
  all: unset;
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.5rem 0.4rem;
  width: 100%;
  cursor: pointer;
  border-radius: 4px;
  box-sizing: border-box;
}

.history-btn:hover {
  background-color: oklch(0.93 0.005 260);
}

.history-btn.history-selected {
  background-color: oklch(0.96 0.02 250);
}

/* Undone entries render as a static div (not navigable) — show them as inert. */
.history-item.skipped .history-btn {
  cursor: default;
}

.history-item.skipped .history-btn:hover {
  background-color: transparent;
}

/* History diff annotations */
.history-addition {
  color: oklch(0.62 0.16 145);
  background-color: oklch(0.92 0.045 145);
}

.history-deletion {
  color: oklch(0.62 0.2 27);
  background-color: oklch(0.9 0.045 20);
  text-decoration: line-through;
}

/* Read-only history view */
.plaintext-history-view {
  padding: 1rem;
  font-family: var(--font-monospace);
  font-size: 0.9rem;
  line-height: 1.5;
  white-space: pre-wrap;
}

/* .history-view-banner shares the grey read-only palette with
   .published-view-banner; both live with the other banner variants above. */
.plaintext-textarea {
  width: 100%;
  flex: 1;
  min-height: 400px;
  padding: 1rem;
  font-family: var(--font-monospace);
  font-size: 0.9rem;
  line-height: 1.5;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  resize: vertical;
  background-color: #fff;
  box-sizing: border-box;
  word-wrap: break-word;
  overflow-wrap: break-word;
  white-space: pre-wrap;
}

.plaintext-textarea:focus {
  outline: none;
  border-color: oklch(0.58 0.22 250);
  box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}

.plaintext-readonly {
  width: 100%;
  flex: 1;
  min-height: 400px;
  padding: 1rem;
  font-family: var(--font-monospace);
  font-size: 0.9rem;
  line-height: 1.5;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  background-color: oklch(0.98 0.003 260);
  overflow: auto;
}

.plaintext-readonly pre {
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.richtext-readonly {
  width: 100%;
  flex: 1;
  min-height: 400px;
  padding: 1rem;
  font-size: 1rem;
  line-height: 1.7;
  overflow: auto;
}

.richtext-readonly h2,
.richtext-readonly h3 {
  font-family: var(--font-serif);
  font-weight: 700;
  line-height: 1.25;
}

.richtext-readonly h2 {
  font-size: 1.5rem;
  margin: 1.5rem 0 0.75rem;
}

.richtext-readonly h3 {
  font-size: 1.2rem;
  margin: 1.25rem 0 0.5rem;
}

.richtext-readonly ul,
.richtext-readonly ol {
  padding-left: 1.75rem;
  margin: 0.5rem 0;
}

.richtext-readonly li {
  min-height: 1.5em;
}

.richtext-readonly p {
  margin: 0.5rem 0;
}

/* =============================================================================
   Remote Cursor Display
   ============================================================================= */
/* Color palette for remote cursors (6 colors) */
:root {
  --cursor-color-0: #e91e63;
  /* pink */
  --cursor-color-1: #2196f3;
  /* blue */
  --cursor-color-2: #4caf50;
  /* green */
  --cursor-color-3: #ff9800;
  /* orange */
  --cursor-color-4: #9c27b0;
  /* purple */
  --cursor-color-5: #00bcd4;
  /* cyan */
  /* Selection highlights (more visible, 40% opacity) */
  --selection-color-0: rgba(233, 30, 99, 0.4);
  --selection-color-1: rgba(33, 150, 243, 0.4);
  --selection-color-2: rgba(76, 175, 80, 0.4);
  --selection-color-3: rgba(255, 152, 0, 0.4);
  --selection-color-4: rgba(156, 39, 176, 0.4);
  --selection-color-5: rgba(0, 188, 212, 0.4);
}

/* Container for textarea + overlay */
.textarea-container {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* Hidden mirror div - matches textarea styling exactly */
.cursor-mirror {
  position: absolute;
  top: 0;
  left: 0;
  visibility: hidden;
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: break-word;
  /* Must match textarea styling exactly */
  padding: 1rem;
  font-family: var(--font-monospace);
  font-size: 0.9rem;
  line-height: 1.5;
  border: 1px solid transparent;
}

/* Overlay for cursor elements */
.cursor-overlay {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 10;
}

/* Individual remote cursor */
.remote-cursor {
  position: absolute;
  pointer-events: auto;
  z-index: 10;
}

/* The cursor caret line */
.cursor-caret {
  width: 2px;
  height: 1.35em;
  /* ~line-height */
  opacity: 0.8;
  animation: cursor-blink 1.2s step-end infinite;
}

@keyframes cursor-blink {
  0%, 100% {
    opacity: 0.8;
  }
  50% {
    opacity: 0.4;
  }
}
/* Small nub above the caret (always visible) */
.cursor-nub {
  position: absolute;
  bottom: 100%;
  left: -3px;
  width: 8px;
  height: 8px;
  border-radius: 2px;
}

/* Flag that expands on hover */
.cursor-flag {
  position: absolute;
  bottom: 100%;
  left: -3px;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: var(--font-sans-serif);
  font-size: 0.7rem;
  white-space: nowrap;
  color: white;
  opacity: 0;
  transform: translateY(5px);
  transition: opacity 0.15s ease, transform 0.15s ease;
  pointer-events: none;
}

/* Show flag on hover */
.remote-cursor:hover .cursor-flag {
  opacity: 1;
  transform: translateY(0);
}

/* Hide nub when flag is shown */
.remote-cursor:hover .cursor-nub {
  opacity: 0;
}

/* Selection highlight for remote cursors (when start != end) */
.cursor-selection {
  position: absolute;
  opacity: 0.2;
  pointer-events: none;
}

/* =============================================================================
   TextEditor Component
   ============================================================================= */
.text-editor {
  font-family: var(--font-monospace);
  font-size: 0.9rem;
  line-height: 1.5;
  padding: 0 1rem 1rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  min-height: 400px;
  background-color: #fff;
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: break-word;
  outline: none;
  cursor: text;
  overflow-y: auto;
  flex: 1;
  user-select: none;
  /* We handle selection ourselves */
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  position: relative;
  /* positioning context for .editor-proxy */
}

/* The hidden control that actually holds focus. A painted div receives no
   clipboard or IME events, so a real focusable element sits inside the editor
   and takes them. It is invisible but must stay laid out: `display: none` or
   `hidden` cannot be focused. */
.editor-proxy {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1em;
  padding: 0;
  margin: 0;
  border: 0;
  outline: none;
  resize: none;
  overflow: hidden;
  opacity: 0;
  z-index: -1;
  white-space: pre;
  /* The editor sets `user-select: none`; the proxy needs the opposite or the
   copy path cannot select the text it just seeded. */
  user-select: text;
  -webkit-user-select: text;
}

/* Where the render model is painted. Separate from the host so that replacing
   it wholesale never re-inserts (and so blurs) the focused proxy.
   Positioned, because it is the containing block for the caret overlay. */
.editor-surface {
  display: block;
  position: relative;
}

.text-editor.richtext-editor {
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.7;
}

.text-editor:focus-within {
  border-color: oklch(0.58 0.22 250);
  box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}

/* Individual text line */
.text-editor .text-line {
  min-height: 1.5em;
  /* Ensure empty lines have height */
  position: relative;
}

/* Empty line placeholder to maintain height */
.text-editor .text-line:empty::after {
  content: " ";
  /* Non-breaking space */
}

/* Local cursor (primary editing cursor).
 *
 * An overlay, not part of the text. As an in-flow `inline-block` the caret was
 * an atomic box sitting at a segment boundary, so the painted DOM depended on
 * where the caret was — and placing it re-flowed the very line that had been
 * measured to place it. That made a measured row target land on a different
 * row. Out of flow, the caret cannot move the text it is measured against.
 *
 * `left`, `top` and `height` are measured per paint and set inline by
 * `renderCaret`; a class cannot carry a computed position. */
.text-editor .cursor {
  position: absolute;
  width: 2px;
  margin-left: -1px;
  background-color: #000;
  pointer-events: none;
}

.text-editor .cursor.blink {
  animation: text-editor-blink 1s step-end infinite;
}

@keyframes text-editor-blink {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
/* Text selection highlight */
.text-editor .selection {
  background-color: oklch(0.87 0.06 245);
}

/* When editor is not focused, dim the selection */
.text-editor:not(:focus-within) .selection {
  background-color: oklch(0.85 0.008 260);
}

/* Remote cursor (other users) */
.text-editor .remote-cursor {
  display: inline-block;
  width: 2px;
  height: 1.2em;
  vertical-align: text-bottom;
  margin-left: -1px;
  margin-right: -1px;
  position: relative;
  opacity: 0.8;
}

/* Expanded hover zone - 5px on each side, doesn't block clicks */
.text-editor .remote-cursor::before {
  content: "";
  position: absolute;
  top: -2px;
  bottom: -2px;
  left: -5px;
  right: -5px;
}

/* Remote cursor name flag */
.text-editor .remote-cursor-flag {
  position: absolute;
  bottom: 100%;
  left: -3px;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: var(--font-sans-serif);
  font-size: 0.65rem;
  white-space: nowrap;
  color: white;
  opacity: 0;
  transform: translateY(5px);
  transition: opacity 0.15s ease, transform 0.15s ease;
  pointer-events: none;
  z-index: 10;
}

.text-editor .remote-cursor:hover .remote-cursor-flag {
  opacity: 1;
  transform: translateY(0);
}

/* Remote selection highlight */
.text-editor .remote-selection {
  border-radius: 2px;
}

/* Remote selection start marker (shows display name at beginning of selection) */
.text-editor .remote-selection-start {
  position: relative;
  display: inline;
}

.text-editor .remote-selection-flag {
  position: absolute;
  bottom: 100%;
  left: 0;
  font-size: 0.7rem;
  padding: 1px 4px;
  border-radius: 3px 3px 3px 0;
  white-space: nowrap;
  color: white;
  font-weight: 500;
  z-index: 10;
  pointer-events: none;
}

/* Color variants for selection flags */
.text-editor .remote-selection-flag.color-0 {
  background-color: var(--cursor-color-0);
}

.text-editor .remote-selection-flag.color-1 {
  background-color: var(--cursor-color-1);
}

.text-editor .remote-selection-flag.color-2 {
  background-color: var(--cursor-color-2);
}

.text-editor .remote-selection-flag.color-3 {
  background-color: var(--cursor-color-3);
}

.text-editor .remote-selection-flag.color-4 {
  background-color: var(--cursor-color-4);
}

.text-editor .remote-selection-flag.color-5 {
  background-color: var(--cursor-color-5);
}

/* =============================================================================
   Cursor Color Variants (consolidated)
   Applied to: .cursor-caret, .cursor-nub, .cursor-flag, .cursor-selection,
               .text-editor .remote-cursor, .text-editor .remote-cursor-flag,
               .text-editor .remote-selection
   ============================================================================= */
/* Cursor elements use solid colors */
.cursor-caret.color-0, .cursor-nub.color-0, .cursor-flag.color-0, .cursor-selection.color-0,
.text-editor .remote-cursor.color-0, .text-editor .remote-cursor-flag.color-0 {
  background-color: var(--cursor-color-0);
}

.cursor-caret.color-1, .cursor-nub.color-1, .cursor-flag.color-1, .cursor-selection.color-1,
.text-editor .remote-cursor.color-1, .text-editor .remote-cursor-flag.color-1 {
  background-color: var(--cursor-color-1);
}

.cursor-caret.color-2, .cursor-nub.color-2, .cursor-flag.color-2, .cursor-selection.color-2,
.text-editor .remote-cursor.color-2, .text-editor .remote-cursor-flag.color-2 {
  background-color: var(--cursor-color-2);
}

.cursor-caret.color-3, .cursor-nub.color-3, .cursor-flag.color-3, .cursor-selection.color-3,
.text-editor .remote-cursor.color-3, .text-editor .remote-cursor-flag.color-3 {
  background-color: var(--cursor-color-3);
}

.cursor-caret.color-4, .cursor-nub.color-4, .cursor-flag.color-4, .cursor-selection.color-4,
.text-editor .remote-cursor.color-4, .text-editor .remote-cursor-flag.color-4 {
  background-color: var(--cursor-color-4);
}

.cursor-caret.color-5, .cursor-nub.color-5, .cursor-flag.color-5, .cursor-selection.color-5,
.text-editor .remote-cursor.color-5, .text-editor .remote-cursor-flag.color-5 {
  background-color: var(--cursor-color-5);
}

/* Remote selection highlights use translucent colors */
.text-editor .remote-selection.color-0 {
  background-color: var(--selection-color-0);
}

.text-editor .remote-selection.color-1 {
  background-color: var(--selection-color-1);
}

.text-editor .remote-selection.color-2 {
  background-color: var(--selection-color-2);
}

.text-editor .remote-selection.color-3 {
  background-color: var(--selection-color-3);
}

.text-editor .remote-selection.color-4 {
  background-color: var(--selection-color-4);
}

.text-editor .remote-selection.color-5 {
  background-color: var(--selection-color-5);
}

/* =============================================================================
   Sheet Focus Indicators
   Colored borders and name tags for remote users focused on model/field elements.
   ============================================================================= */
/* Focus overlay - positioned absolutely around focused elements */
.sheet-focus-overlay {
  border: 2px solid;
  border-radius: 4px;
  box-sizing: border-box;
}

/* Color variants for focus overlay borders */
.sheet-focus-overlay.color-0 {
  border-color: var(--cursor-color-0);
}

.sheet-focus-overlay.color-1 {
  border-color: var(--cursor-color-1);
}

.sheet-focus-overlay.color-2 {
  border-color: var(--cursor-color-2);
}

.sheet-focus-overlay.color-3 {
  border-color: var(--cursor-color-3);
}

.sheet-focus-overlay.color-4 {
  border-color: var(--cursor-color-4);
}

.sheet-focus-overlay.color-5 {
  border-color: var(--cursor-color-5);
}

/* Name tag at bottom-left of focused element */
.sheet-focus-tag {
  position: absolute;
  bottom: -18px;
  left: -2px;
  padding: 1px 6px;
  border-radius: 0 0 3px 3px;
  font-family: var(--font-sans-serif);
  font-size: 0.65rem;
  font-weight: 500;
  white-space: nowrap;
  color: white;
}

/* Color variants for focus tags */
.sheet-focus-tag.color-0 {
  background-color: var(--cursor-color-0);
}

.sheet-focus-tag.color-1 {
  background-color: var(--cursor-color-1);
}

.sheet-focus-tag.color-2 {
  background-color: var(--cursor-color-2);
}

.sheet-focus-tag.color-3 {
  background-color: var(--cursor-color-3);
}

.sheet-focus-tag.color-4 {
  background-color: var(--cursor-color-4);
}

.sheet-focus-tag.color-5 {
  background-color: var(--cursor-color-5);
}

/* =============================================================================
   SearchInput Component (single-line text input for search boxes)
   ============================================================================= */
.search-input {
  display: inline-block;
  font-family: var(--font-sans-serif);
  font-size: 0.9rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  background-color: #fff;
  min-width: 180px;
  outline: none;
  cursor: text;
  white-space: nowrap;
  overflow: hidden;
  vertical-align: middle;
}

.search-input:focus {
  border-color: oklch(0.58 0.22 250);
  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.1);
}

.search-input .search-placeholder {
  color: oklch(0.55 0.01 260);
  pointer-events: none;
}

.search-input .search-cursor {
  display: inline-block;
  width: 1px;
  height: 1em;
  background-color: #000;
  vertical-align: text-bottom;
  margin-left: -0.5px;
  margin-right: -0.5px;
}

.search-input .search-cursor.blink {
  animation: search-cursor-blink 1s step-end infinite;
}

@keyframes search-cursor-blink {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
.search-input .search-selection {
  background-color: oklch(0.87 0.06 245);
}

.search-input:not(:focus) .search-selection {
  background-color: oklch(0.85 0.008 260);
}

/* =============================================================================
   Format Toolbar (Richtext Documents)
   ============================================================================= */
.format-toolbar {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem 0.5rem;
  background-color: oklch(0.93 0.005 260);
  border-radius: 4px;
  margin-bottom: 0.5rem;
}

.format-btn {
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  background-color: #fff;
  cursor: pointer;
  font-family: var(--font-serif);
  font-size: 0.875rem;
  font-weight: 700;
  color: oklch(0.42 0.008 260);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.15s, border-color 0.15s;
}

.format-btn:hover {
  background-color: oklch(0.98 0.003 260);
  border-color: oklch(0.75 0.01 260);
}

.format-btn:active {
  background-color: oklch(0.93 0.005 260);
}

.format-btn.active,
.format-btn[data-active=true] {
  background-color: oklch(0.89 0.006 260);
  border-color: oklch(0.55 0.01 260);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}

.format-btn.active:hover,
.format-btn[data-active=true]:hover {
  background-color: oklch(0.85 0.008 260);
}

.format-btn.format-italic {
  font-style: italic;
}

.format-btn.format-underline {
  text-decoration: underline;
}

.format-btn.format-strikethrough {
  text-decoration: line-through;
}

/* Full-tier toolbar: several button islands on one row, visually separated. */
.format-toolbars {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.format-toolbars .format-toolbar {
  margin-bottom: 0;
}

/* Heading + list buttons hold text labels, wider than the square inline ones. */
.format-btn.format-h2,
.format-btn.format-h3,
.format-btn.format-ul,
.format-btn.format-ol {
  width: auto;
  min-width: 28px;
  padding: 0 0.4rem;
  font-size: 0.8rem;
}

/* Link toolbar button uses an emoji, not a styled letter. */
.format-btn.format-link {
  font-family: inherit;
  font-weight: normal;
  font-size: 1rem;
}

/* Link modal overlay (display toggled by JS). */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1001;
}

.modal-dialog {
  background-color: #fff;
  padding: 1.5rem;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  max-width: 440px;
  width: 90%;
}

.modal-dialog h3 {
  margin: 0 0 1rem;
}

.modal-body .form-group {
  margin-bottom: 0.75rem;
}

.modal-body .form-group label {
  display: block;
  margin-bottom: 0.25rem;
  font-weight: 600;
  font-size: 0.875rem;
}

.link-type-radios label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: normal;
  cursor: pointer;
}

.link-type-radios label + label {
  margin-top: 0.25rem;
}

.modal-footer {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin-top: 1rem;
}

/* Link rendering inside the live editor and readonly views. */
.text-editor a,
.plaintext-readonly a,
.richtext-readonly a {
  color: #1971c2;
  text-decoration: underline;
  cursor: pointer;
}

.text-editor a:hover,
.plaintext-readonly a:hover,
.richtext-readonly a:hover {
  color: #1864ab;
}

.richtext-readonly a.heading-anchor {
  text-decoration: none;
}

/* In the editor, links aren't navigable — suppress pointer navigation. */
.text-editor a {
  pointer-events: none;
}

/* Heading rendering inside the live editor. */
.text-editor h2,
.text-editor h3 {
  margin: 1.25rem 0 0.5rem;
  font-family: var(--font-serif);
  font-weight: 700;
  line-height: 1.25;
}

.text-editor h2 {
  font-size: 1.5rem;
}

.text-editor h3 {
  font-size: 1.2rem;
}

/* List rendering inside the live editor. */
.text-editor ul,
.text-editor ol {
  margin: 0;
  padding-left: 1.75rem;
}

.text-editor li {
  min-height: 1.5em;
}

/* Per-line hit-test element (paragraph div, heading div, or list-item span). */
.text-editor .editor-line {
  position: relative;
}

/* Empty line/list-item placeholder so it keeps height and stays clickable. */
.text-editor .editor-line:empty::after {
  content: " ";
  /* Non-breaking space */
}

/* =============================================================================
   Floating Richtext Toolbar (Sheet Cells)
   ============================================================================= */
.richtext-floating-toolbar {
  position: absolute;
  display: none;
  align-items: center;
  gap: 0.125rem;
  padding: 0.125rem 0.25rem;
  background-color: #fff;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  z-index: 1000;
}

.richtext-floating-toolbar.visible {
  display: flex;
}

.richtext-format-btn {
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 3px;
  background-color: #fff;
  cursor: pointer;
  font-family: var(--font-serif);
  font-size: 0.75rem;
  font-weight: 700;
  color: oklch(0.42 0.008 260);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.1s, border-color 0.1s;
}

.richtext-format-btn:hover {
  background-color: oklch(0.98 0.003 260);
  border-color: oklch(0.75 0.01 260);
}

.richtext-format-btn:active {
  background-color: oklch(0.93 0.005 260);
}

.richtext-format-btn[data-active=true] {
  background-color: oklch(0.89 0.006 260);
  border-color: oklch(0.55 0.01 260);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}

.richtext-format-btn.richtext-format-italic {
  font-style: italic;
}

.richtext-format-btn.richtext-format-underline {
  text-decoration: underline;
}

.richtext-format-btn.richtext-format-strikethrough {
  text-decoration: line-through;
}

/* =============================================================================
   New Version Notification (for viewers)
   ============================================================================= */
.new-version-notification {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  background-color: oklch(0.97 0.055 92);
  border: 1px solid oklch(0.85 0.17 90);
  border-radius: 4px;
  margin: 0 1rem 0.75rem 1rem;
  font-size: 0.9rem;
  color: oklch(0.5 0.11 78);
  width: calc(100% - 2rem);
  box-sizing: border-box;
  flex-shrink: 0;
}

/* Notification inside .plaintext-panels (now a flex column) — natural
   content-height row, full width. `flex-basis: 100%` in a column would
   claim the full main axis (vertical) and reintroduce the blowout. */
.plaintext-panels .new-version-notification {
  width: 100%;
  margin: 0 0 0.75rem 0;
  flex: 0 0 auto;
}

.new-version-notification span {
  flex: 1;
}

.new-version-notification a {
  color: oklch(0.37 0.15 258);
  text-decoration: underline;
  font-weight: 500;
  cursor: pointer;
}

.new-version-notification a:hover {
  color: oklch(0.37 0.15 258);
}

.new-version-notification button {
  background: none;
  border: none;
  font-size: 1.25rem;
  color: oklch(0.5 0.11 78);
  cursor: pointer;
  padding: 0;
  line-height: 1;
  opacity: 0.7;
}

.new-version-notification button:hover {
  opacity: 1;
}

/* Responsive adjustments */
@media (max-width: 768px) {
  /* .plaintext-panels is already flex-column at every width; nothing to
   override here. */
  .document-with-panel {
    flex-direction: column;
  }
  .document-side-panel {
    width: auto;
    max-height: 300px;
    border-left: none;
    border-top: 1px solid oklch(0.89 0.006 260);
  }
}
/* =============================================================================
   Attachment Document Styles
   ============================================================================= */
/* Attachment upload modal */
#attachment-upload-modal {
  display: none;
}

#attachment-upload-modal[data-visible=true] {
  display: flex;
}

.attachment-upload-modal {
  max-width: 500px;
}

/* Attachment upload error display */
.attachment-upload-error {
  display: none;
  color: oklch(0.58 0.2 25);
  background-color: oklch(0.97 0.012 25);
  border: 1px solid oklch(0.58 0.2 25);
  padding: 0.75rem 1rem;
  border-radius: 4px;
  margin-bottom: 1rem;
  font-size: 0.9rem;
}

.attachment-upload-error[data-visible=true] {
  display: block;
}

/* Shown when the chosen replacement has a different content type from the
   current file, which changes how the document is displayed. */
.attachment-type-warning {
  display: none;
}

.attachment-type-warning[data-visible=true] {
  display: block;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border: 1px solid transparent;
  font-size: 0.9rem;
  border-radius: 4px;
  padding: 0.75rem 1rem;
  background-color: oklch(0.97 0.055 92);
  border: 1px solid oklch(0.85 0.17 90);
  color: oklch(0.5 0.11 78);
}

.attachment-upload-modal .form-group {
  margin-bottom: 1rem;
}

.attachment-upload-modal .form-group label {
  display: block;
  margin-bottom: 0.25rem;
  font-weight: 500;
}

.attachment-upload-modal .form-group input[type=text] {
  width: 100%;
  padding: 0.5rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  font-size: 1rem;
}

/* Drop zone */
.attachment-drop-zone {
  border: 2px dashed oklch(0.85 0.008 260);
  border-radius: 8px;
  padding: 2rem;
  text-align: center;
  transition: border-color 0.2s, background-color 0.2s;
  position: relative;
  min-height: 180px;
}

.attachment-drop-zone:hover {
  border-color: oklch(0.75 0.01 260);
}

.attachment-drop-zone.drag-over,
.attachment-drop-zone[data-drag-over=true] {
  border-color: oklch(0.7 0.15 244);
  background-color: oklch(0.96 0.02 250);
}

.drop-zone-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

.attachment-drop-zone.has-file .drop-zone-content {
  display: none;
}

.drop-zone-icon {
  font-size: 3rem;
  margin: 0;
}

.drop-zone-text {
  color: oklch(0.42 0.008 260);
  margin: 0;
}

.drop-zone-browse {
  cursor: pointer;
  margin-top: 0.5rem;
}

.drop-zone-browse input[type=file] {
  display: none;
}

.drop-zone-hint {
  color: oklch(0.57 0.02 250);
  font-size: 0.875rem;
  margin: 0;
  transition: color 0.2s ease;
}

.drop-zone-hint.error {
  color: oklch(0.58 0.2 25);
  font-weight: 500;
}

/* File preview (shown when file selected) */
.attachment-file-preview {
  display: none;
  align-items: center;
  gap: 1rem;
  padding: 1rem;
  background: oklch(0.98 0.003 260);
  border-radius: 4px;
}

.attachment-drop-zone.has-file .attachment-file-preview {
  display: flex;
}

.attachment-file-preview .file-icon {
  font-size: 2rem;
}

.attachment-file-preview .file-name {
  flex: 1;
  font-weight: 500;
  word-break: break-all;
}

.attachment-file-preview .file-size {
  color: oklch(0.57 0.02 250);
  font-size: 0.875rem;
}

.attachment-file-preview .unattach-btn {
  background: none;
  border: none;
  color: oklch(0.75 0.01 260);
  font-size: 1.25rem;
  cursor: pointer;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
}

.attachment-file-preview .unattach-btn:hover {
  color: oklch(0.62 0.2 27);
  background: oklch(0.97 0.012 25);
}

/* Calendar CSV import modal.

   The drop zone, its hint, the file chip and the error banner reuse the
   attachment upload classes verbatim (only the element ids differ), so nothing
   here restates them. What is new is the preview: the counts line, the list of
   per-row notes, and the sample table. */
#calendar-csv-import-modal {
  display: none;
}

#calendar-csv-import-modal[data-visible=true] {
  display: flex;
}

/* Wider than the attachment modal, because the preview table has four columns. */
.calendar-csv-import-modal {
  max-width: min(720px, 90vw);
}

.csv-import-intro {
  margin: 0 0 1rem;
  color: oklch(0.55 0.01 260);
  font-size: 0.9rem;
}

.csv-import-summary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border: 1px solid transparent;
  font-size: 0.9rem;
  border-radius: 4px;
}

.csv-import-summary-good {
  background-color: oklch(0.92 0.045 145);
  border-color: oklch(0.62 0.16 145);
  color: oklch(0.35 0.1 145);
}

.csv-import-summary-bad {
  background-color: oklch(0.97 0.055 92);
  border-color: oklch(0.85 0.17 90);
  color: oklch(0.5 0.11 78);
}

/* Quiet asides under the summary: ignored columns, truncation, "and N more". */
.csv-import-ignored {
  margin: 0.25rem 0;
  color: oklch(0.55 0.01 260);
  font-size: 0.85rem;
}

/* Open-sided list: the modal already supplies the edges. */
.csv-import-warnings {
  list-style: none;
  padding: 0;
  margin: 1rem 0;
  max-height: 12rem;
  overflow-y: auto;
  font-size: 0.85rem;
}

.csv-import-warnings li {
  padding: 0.75rem 0.5rem;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.csv-import-warnings li:last-child {
  border-bottom: none;
}

.csv-import-warning-row {
  color: oklch(0.55 0.01 260);
}

.csv-import-warning-fatal .csv-import-warning-text {
  color: oklch(0.32 0.12 22);
}

.csv-import-preview-scroll {
  max-height: 18rem;
  overflow-y: auto;
  overflow-x: auto;
}

.csv-import-preview-table {
  width: 100%;
  font-size: 0.85rem;
}

/* Email preview: the generated email HTML, shown in an isolated iframe so the
   application stylesheet cannot reach it. Same shape as .attachment-viewer —
   a fixed-height frame that scrolls internally, since sizing an iframe to its
   content needs JavaScript. */
.email-preview {
  margin: 1rem;
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

.email-preview-caption {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  color: oklch(0.42 0.008 260);
}

.email-preview-frame {
  border-radius: 8px;
  width: 100%;
  height: 70vh;
  min-height: 400px;
  border: 1px solid oklch(0.89 0.006 260);
  display: block;
  background: #fff;
  overscroll-behavior: contain;
}

/* Attachment viewer (iframe) */
.attachment-viewer {
  margin-top: 1rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  overflow: hidden;
  background: oklch(0.98 0.003 260);
}

.attachment-viewer iframe {
  width: 100%;
  height: 80vh;
  min-height: 500px;
  border: none;
  display: block;
  /* Keep scroll/zoom gestures inside the frame when possible */
  overscroll-behavior: contain;
}

/* Shown in place of the iframe when an attachment document has no stored file —
   a bug or a half-applied migration, never a normal state. */
.attachment-viewer.attachment-missing {
  padding: 2rem;
  text-align: center;
  color: oklch(0.42 0.008 260);
}

/* Badges in the version-history list: the file type (only when versions
   disagree) and which version is current. */
.attachment-type-badge,
.attachment-current-badge,
.attachment-version-badge {
  border-radius: 4px;
  padding: 0 0.35rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.attachment-type-badge {
  background-color: oklch(0.89 0.006 260);
  color: oklch(0.42 0.008 260);
}

.attachment-current-badge,
.attachment-version-badge {
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.37 0.15 258);
}

.attachment-version-list .history-summary {
  display: block;
  font-weight: 600;
  font-size: 0.82rem;
  color: oklch(0.24 0.006 260);
}

/* Attachment document view */
.attachment-document .document-header {
  margin-bottom: 1rem;
}

.attachment-document .attachment-info {
  color: oklch(0.57 0.02 250);
}

/* Document type badge (already exists but adding attachment variant) */
.document-type-badge {
  background: oklch(0.89 0.006 260);
  color: oklch(0.42 0.008 260);
  padding: 0.125rem 0.5rem;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 500;
  margin-left: 0.5rem;
}

/* =============================================================================
   Auth Page Layout (Login / Register)
   ============================================================================= */
.auth-page {
  display: flex;
  justify-content: center;
  min-height: 100vh;
  background: oklch(0.7 0.15 244);
}

.auth-container {
  background: #fff;
  width: 100%;
  max-width: 480px;
  padding: 3rem 2rem;
  box-shadow: -4px 0 12px rgba(0, 0, 0, 0.15), 4px 0 12px rgba(0, 0, 0, 0.15);
}

.auth-site-name {
  font-family: var(--font-serif);
  text-align: center;
  font-size: 2rem;
  font-weight: 700;
  margin: 0 0 0.5rem;
}

.auth-title {
  text-align: center;
  margin: 0 0 1.5rem;
}

.auth-form fieldset {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.auth-form label {
  margin-bottom: -0.5rem;
}

.auth-link {
  text-align: center;
  margin-top: 1.5rem;
}

/* =============================================================================
   Dual List Select Component
   ============================================================================= */
.dual-list-select {
  display: flex;
  gap: 1.5rem;
}

.dual-list-active,
.dual-list-inactive {
  flex: 1;
  min-width: 200px;
}

.dual-list-active {
  position: relative;
}

.dual-list-active h4,
.dual-list-inactive h4 {
  margin: 0 0 0.5rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: oklch(0.42 0.008 260);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.dual-list-items {
  min-height: 100px;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  background: #fff;
  padding: 0.25rem;
}

.dual-list-item {
  display: flex;
  align-items: center;
  padding: 0.5rem 0.75rem;
  margin: 0.25rem 0;
  background: oklch(0.98 0.003 260);
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  cursor: grab;
  user-select: none;
  transition: background 0.15s ease, box-shadow 0.15s ease;
}

.dual-list-item:hover {
  background: oklch(0.93 0.005 260);
}

.dual-list-item:active {
  cursor: grabbing;
}

.dual-list-item:focus {
  outline: 2px solid oklch(0.7 0.15 244);
  outline-offset: -2px;
  background: oklch(0.96 0.02 250);
}

.dual-list-grip {
  color: oklch(0.75 0.01 260);
  margin-right: 0.5rem;
  font-size: 1rem;
  line-height: 1;
}

.dual-list-item-label {
  flex: 1;
  font-size: 0.9375rem;
}

.dual-list-item.dragging-self {
  opacity: 0.4;
  background: oklch(0.89 0.006 260);
}

.dual-list-indicator {
  position: absolute;
  left: 0.25rem;
  right: 0.25rem;
  height: 6px;
  background: oklch(0.7 0.15 244);
  border-radius: 3px;
  display: none;
  pointer-events: none;
  z-index: 10;
}

.dual-list-select[data-dragging=true] .dual-list-indicator {
  display: block;
}

.dual-list-inactive-target[data-drag-over=true] {
  background: oklch(0.96 0.02 250);
  border-color: oklch(0.7 0.15 244);
}

/* =============================================================================
   Single List (generic editable + drag-reorderable rows)
   ============================================================================= */
.single-list {
  position: relative;
}

.single-list-rows {
  min-height: 2.5rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  background: #fff;
  padding: 0.25rem;
}

.single-list-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.375rem 0.5rem;
  margin: 0.25rem 0;
  background: oklch(0.98 0.003 260);
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
}

.single-list-grip {
  color: oklch(0.75 0.01 260);
  font-size: 1rem;
  line-height: 1;
  cursor: grab;
  user-select: none;
}

.single-list-grip:active {
  cursor: grabbing;
}

.single-list-grip:focus {
  outline: 2px solid oklch(0.7 0.15 244);
  outline-offset: 2px;
  color: oklch(0.7 0.15 244);
  border-radius: 3px;
}

.single-list-row.dragging-self {
  opacity: 0.4;
  background: oklch(0.89 0.006 260);
}

.single-list-row-error {
  flex-basis: 100%;
  color: oklch(0.58 0.2 25);
  font-size: 0.8125rem;
}

.single-list-delete {
  margin-left: auto;
  background: none;
  border: none;
  color: oklch(0.75 0.01 260);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
}

.single-list-delete:hover {
  color: oklch(0.62 0.2 27);
  background: oklch(0.9 0.045 20);
}

.single-list-add {
  margin-top: 0.5rem;
}

.single-list-indicator {
  position: absolute;
  left: 0.25rem;
  right: 0.25rem;
  height: 6px;
  background: oklch(0.7 0.15 244);
  border-radius: 3px;
  display: none;
  pointer-events: none;
  z-index: 10;
}

/* Show the drop indicator on every list that is a valid target for the current
   drag (the source list and any same-kind sibling — e.g. other sections' field
   lists), so cross-list drop areas are visible, not just the source. */
.single-list[data-drop-active=true] .single-list-indicator {
  display: block;
}

/* Highlight valid field drop targets during a field drag so other sections
   visibly accept the row. Scoped to field lists: the sections list wraps every
   section, so outlining its rows would draw a box through all of them. */
.single-list[data-list-kind=fields][data-drop-active=true] .single-list-rows {
  outline: 2px dashed oklch(0.87 0.06 245);
  outline-offset: 2px;
}

#single-list-delete-modal {
  display: none;
}

#single-list-delete-modal[data-visible=true] {
  display: flex;
}

/* =============================================================================
   Phone Numbers (editor row content + read-only profile list)
   ============================================================================= */
.phone-kind {
  flex: 0 0 auto;
}

.phone-number-input {
  flex: 1 1 auto;
  min-width: 8rem;
}

.phone-can-text {
  flex: 0 0 auto;
  font-size: 0.9375rem;
}

.phone-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.phone-list li {
  padding: 0.35rem 0.6rem;
  display: flex;
  align-items: center;
  border-radius: 3px;
}

/* Zebra striping so the eye tracks across each row. */
.phone-list li:nth-child(even) {
  background: oklch(0.98 0.003 260);
}

/* tel:/sms: action links, right-justified. Hidden until the container's
   data-can-call / data-can-text resolve (set by the server from the request
   platform header and re-applied by WASM on load). */
.phone-actions {
  margin-left: auto;
  display: inline-flex;
  gap: 0.5rem;
  padding-left: 0.75rem;
}

.phone-action {
  text-decoration: none;
  font-size: 1rem;
  line-height: 1;
}

.phone-action.phone-call,
.phone-action.phone-text {
  display: none;
}

.profile-phones[data-can-call=true] .phone-action.phone-call {
  display: inline-flex;
}

.profile-phones[data-can-text=true] .phone-action.phone-text {
  display: inline-flex;
}

.phone-list-kind {
  display: inline-block;
  min-width: 3.5rem;
  color: oklch(0.57 0.02 250);
  font-size: 0.8125rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.phone-list-number {
  font-variant-numeric: tabular-nums;
}

/* =============================================================================
   Email Addresses (editor rows + read-only profile list)
   ============================================================================= */
/* Editor: two stacked inputs (address + optional note) inside each row. */
.email-fields {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.email-address-input,
.email-note-input {
  width: 100%;
}

.email-note-input {
  font-style: italic;
}

/* The account row: read-only address, taller, with an explanatory line. */
.email-address-input[readonly] {
  background: oklch(0.98 0.003 260);
  color: oklch(0.42 0.008 260);
  cursor: default;
}

.email-account-note {
  margin: 0.15rem 0 0;
  font-size: 0.8125rem;
  color: oklch(0.57 0.02 250);
}

/* Read-only profile list. */
.email-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.email-list li {
  display: flex;
  align-items: center;
  padding: 0.35rem 0.6rem;
  border-radius: 3px;
}

.email-list li:nth-child(even) {
  background: oklch(0.98 0.003 260);
}

.email-list-main {
  flex: 1 1 auto;
  min-width: 0;
}

.email-list-note {
  font-style: italic;
  color: oklch(0.57 0.02 250);
  font-size: 0.875rem;
}

/* mailto: link, right-justified, gated by the platform's can_email. */
.email-actions {
  margin-left: auto;
  display: inline-flex;
  gap: 0.5rem;
  padding-left: 0.75rem;
}

.email-action {
  text-decoration: none;
  font-size: 1rem;
  line-height: 1;
}

.email-action.email-mail {
  display: none;
}

.profile-emails[data-can-email=true] .email-action.email-mail {
  display: inline-flex;
}

/* =============================================================================
   Quick Links Section (User Settings)
   ============================================================================= */
.quick-links-section {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid oklch(0.89 0.006 260);
}

.quick-links-section h2 {
  margin-top: 0;
}

.quick-links-section .form-buttons {
  margin-top: 1rem;
}

/* =============================================================================
   Reporting Page (Dashboard)
   ============================================================================= */
.reporting-page {
  padding: 1rem 2rem;
  max-width: 1200px;
  margin: 0 auto;
}

.reporting-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.reporting-header h1 {
  margin: 0;
}

.reporting-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
  padding: 0.75rem;
  background-color: oklch(0.98 0.003 260);
  border-radius: 4px;
}

.reporting-controls .search-input {
  flex: 1;
  max-width: 300px;
}

.reporting-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.reporting-row {
  padding: 0.75rem 0.5rem;
  border-bottom: 1px solid oklch(0.93 0.005 260);
}

.reporting-row:last-child {
  border-bottom: none;
}

.reporting-row.has-honeypot {
  background-color: oklch(0.97 0.055 92);
}

.reporting-row-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

.reporting-ip {
  flex-shrink: 0;
}

.reporting-ip code {
  font-family: "SF Mono", "Consolas", "Liberation Mono", monospace;
  font-size: 0.9rem;
  background: oklch(0.93 0.005 260);
  padding: 0.2rem 0.4rem;
  border-radius: 3px;
}

.reporting-users {
  list-style: none;
  padding: 0;
  margin: 0 0 0 1rem;
  border-left: 2px solid oklch(0.93 0.005 260);
  padding-left: 1rem;
}

.reporting-user-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.35rem 0;
  gap: 1rem;
}

.reporting-user-row:hover {
  background-color: rgba(0, 0, 0, 0.02);
}

.reporting-user .user-link {
  color: oklch(0.52 0.2 258);
  text-decoration: none;
  font-weight: 500;
}

.reporting-user .user-link:hover {
  text-decoration: underline;
}

.reporting-user .anonymous {
  color: oklch(0.55 0.01 260);
  font-size: 0.85rem;
}

.reporting-user-stats {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
  font-size: 0.8rem;
}

.reporting-updated {
  font-size: 0.8rem;
  color: oklch(0.55 0.01 260);
}

.reporting-stats {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-shrink: 0;
}

.reporting-stats .stat {
  font-size: 0.85rem;
  padding: 0.25rem 0.5rem;
  border-radius: 4px;
  background: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.reporting-stats .stat.honeypot {
  background: oklch(0.97 0.055 92);
  color: oklch(0.5 0.11 78);
  font-weight: 600;
}

.reporting-erase {
  font-size: 0.75rem;
  padding: 0.2rem 0.5rem;
  border: 1px solid oklch(0.9 0.045 20);
  border-radius: 4px;
  background: oklch(0.9 0.045 20);
  color: oklch(0.32 0.12 22);
  cursor: pointer;
}

.reporting-erase:hover {
  background: oklch(0.9 0.045 20);
}

.reporting-empty {
  text-align: center;
  padding: 3rem 1rem;
  color: oklch(0.55 0.01 260);
}

.session-lookup {
  margin: 1.5rem 0;
}

.session-lookup-input {
  width: 22rem;
  max-width: 100%;
  margin-right: 0.5rem;
}

.session-timeline-result {
  margin-top: 1rem;
  padding: 0.75rem 1rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 6px;
  background: oklch(0.98 0.003 260);
}

.session-steps .session-time,
.session-errors .session-time {
  color: oklch(0.55 0.01 260);
  font-size: 0.8rem;
}

.session-args {
  color: oklch(0.55 0.01 260);
}

.session-error-msg {
  color: oklch(0.32 0.12 22);
}

.reporting-empty p:first-child {
  font-size: 3rem;
  margin-bottom: 0.5rem;
}

.reporting-empty .hint {
  font-size: 0.9rem;
  color: oklch(0.63 0.012 260);
}

.reporting-pagination {
  margin-top: 1rem;
}

/* =============================================================================
 * Drag and Drop Reordering for Models and Fields
 * ============================================================================= */
/* Drag handles */
.drag-handle {
  cursor: grab;
  color: oklch(0.75 0.01 260);
  padding: 0.25rem;
  user-select: none;
  font-size: 1rem;
  line-height: 1;
  flex-shrink: 0;
}

.drag-handle:hover {
  color: oklch(0.55 0.01 260);
}

.drag-handle:active {
  cursor: grabbing;
}

/* Drop zones - large hit area, small visual indicator */
.drop-zone {
  position: relative;
  height: 0;
  pointer-events: none;
  z-index: 10;
}

/* The visible indicator line (pseudo-element) */
.drop-zone::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 4px;
  border-radius: 2px;
  background: transparent;
  transition: background-color 0.15s;
}

/* Model drop zones - extend hit area into model card padding (16px) */
.model-drop-zone {
  margin: -16px 0;
  padding: 16px 0;
}

/* Field drop zones - smaller hit area for tighter spacing */
.field-drop-zone {
  margin: -8px 0;
  padding: 8px 0;
}

/* Enable pointer events and show indicator when dragging a model */
[data-dragging-model=true] .model-drop-zone {
  pointer-events: auto;
}

[data-dragging-model=true] .model-drop-zone::after {
  height: 8px;
  background-color: oklch(0.93 0.005 260);
}

[data-dragging-model=true] .model-drop-zone.drag-over::after {
  height: 12px;
  background-color: oklch(0.7 0.15 244);
}

/* Enable pointer events and show indicator when dragging a field */
.field-drop-zone.show-field-zone {
  pointer-events: auto;
}

.field-drop-zone.show-field-zone::after {
  background-color: oklch(0.93 0.005 260);
}

.field-drop-zone.show-field-zone.drag-over::after {
  background-color: oklch(0.7 0.15 244);
  height: 6px;
}

/* Dragging state on source item */
.model-card.dragging {
  opacity: 0.4;
  border-color: oklch(0.75 0.01 260);
}

.model-field-row.dragging {
  opacity: 0.4;
  background-color: oklch(0.93 0.005 260);
}

/* =============================================================================
   Object Row Drag-and-Drop (Sheet Data Table)
   ============================================================================= */
/* Order column header - narrow, fits drag handle + 3-digit number */
.order-column {
  width: 44px !important;
  min-width: 44px !important;
  max-width: 44px !important;
  padding: 0.25rem 2px !important;
  text-align: center;
  font-size: 0.7rem;
  color: oklch(0.75 0.01 260);
}

/* Order cell - contains drag handle and order number */
.order-cell {
  width: 44px !important;
  min-width: 44px !important;
  max-width: 44px !important;
  padding: 0 2px !important;
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
  position: relative;
}

/* Order number display - 3 digits, monospace */
.order-number {
  font-family: var(--font-monospace);
  font-size: 0.7rem;
  color: oklch(0.75 0.01 260);
  margin-left: 1px;
}

/* Row menu dropdown */
.row-menu-dropdown {
  display: inline-block;
  position: relative;
  margin-left: 2px;
}

.row-menu-trigger {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 2px;
  font-size: 0.6rem;
  color: oklch(0.85 0.008 260);
  line-height: 1;
  vertical-align: middle;
  opacity: 0;
  transition: opacity 0.15s;
}

.order-cell:hover .row-menu-trigger,
.row-menu-dropdown.open .row-menu-trigger {
  opacity: 1;
}

.row-menu-trigger:hover {
  color: oklch(0.55 0.01 260);
}

.row-menu-dropdown .dropdown-menu {
  min-width: 100px;
  left: 0;
  top: 100%;
  z-index: 1000;
}

/* Deleted row styling - use color changes instead of opacity so dropdown isn't affected */
tr.deleted-row {
  background-color: oklch(0.98 0.003 260);
}

tr.deleted-row td:not(.order-cell) {
  text-decoration: line-through;
  text-decoration-color: oklch(0.58 0.2 25);
}

tr.deleted-row .spreadsheet-cell,
tr.deleted-row .spreadsheet-cell-readonly {
  text-decoration: line-through;
  text-decoration-color: oklch(0.58 0.2 25);
  color: #aaa;
}

tr.deleted-row .order-number,
tr.deleted-row .drag-handle {
  color: oklch(0.85 0.008 260);
}

tr.deleted-row .kind-cell {
  color: #aaa;
}

/* Disabled drag handle (when sorting is active) */
.drag-handle-disabled {
  display: inline-block;
  color: oklch(0.85 0.008 260);
  padding: 0;
  user-select: none;
  font-size: 0.75rem;
  line-height: 1;
  cursor: not-allowed;
}

/* Object drag handle styling */
.object-drag-handle {
  display: inline-block;
  cursor: grab;
  color: oklch(0.75 0.01 260);
  padding: 0;
  user-select: none;
  font-size: 0.75rem;
  line-height: 1;
  opacity: 0.6;
  transition: opacity 0.15s, color 0.15s;
  vertical-align: middle;
}

.object-drag-handle:hover {
  color: oklch(0.55 0.01 260);
  opacity: 1;
}

.object-drag-handle:active {
  cursor: grabbing;
}

/* Object drop zones - invisible rows that overlap adjacent data rows */
tr.object-drop-zone {
  height: 0;
  pointer-events: none;
  position: relative;
}

tr.object-drop-zone td {
  padding: 0 !important;
  border: none !important;
  height: 0;
  line-height: 0;
  position: relative;
}

/* Drop zone indicator - absolutely positioned, overlaps rows above/below */
tr.object-drop-zone td::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 4px;
  border-radius: 2px;
  background: transparent;
  transition: background-color 0.15s;
  transform: translateY(-50%);
  z-index: 10;
  pointer-events: none;
}

/* Show drop zones when dragging - expand hit area but NOT visual height */
tr.object-drop-zone.show-object-zone {
  pointer-events: auto;
}

/* Expand the clickable area above/below by using a pseudo-element on the td */
tr.object-drop-zone.show-object-zone td {
  height: 0;
}

/* Use ::before to create a large invisible hit area that overlaps rows */
tr.object-drop-zone.show-object-zone td::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -26px;
  bottom: -26px;
  z-index: 5;
  cursor: pointer;
}

tr.object-drop-zone.show-object-zone td::after {
  background-color: rgba(66, 153, 225, 0.3);
}

tr.object-drop-zone.show-object-zone.drag-over td::after {
  background-color: oklch(0.7 0.15 244);
  height: 6px;
}

/* Dragging state on source row */
tr.dragging {
  opacity: 0.4;
}

tr.dragging td {
  background-color: oklch(0.93 0.005 260) !important;
}

/* Body-level indicator for object dragging */
body.dragging-object .spreadsheet-table tr:not(.dragging):not(.object-drop-zone) {
  cursor: default;
}

/* Dropdown positioning - above trigger when not enough space below */
.dropdown-menu.dropdown-above {
  margin-bottom: 0.25rem;
}

/* =============================================================================
   Validated Input Components
   ============================================================================= */
.validated-input {
  margin-bottom: 1rem;
}

.validated-input > label {
  display: block;
  margin-bottom: 0.25rem;
  font-weight: 500;
  color: var(--text-primary, oklch(0.3 0.006 260));
}

.validated-input-wrapper {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}

.validated-input-field {
  flex: 1;
  padding: 0.5rem 0.75rem;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  font-size: 1rem;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.validated-input-field:focus {
  outline: none;
  border-color: oklch(0.7 0.15 244);
  box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.15);
}

.validated-input-field.is-invalid,
.pure-form .validated-input-field.is-invalid {
  border-color: oklch(0.58 0.2 25);
  border-width: 2px;
}

.validated-input-field.is-invalid:focus,
.pure-form .validated-input-field.is-invalid:focus {
  border-color: oklch(0.58 0.2 25);
  box-shadow: 0 0 0 3px rgba(229, 62, 62, 0.15);
}

.validated-input-field.is-valid,
.pure-form .validated-input-field.is-valid {
  border-color: oklch(0.62 0.16 145);
}

.validated-input-field.is-valid:focus,
.pure-form .validated-input-field.is-valid:focus {
  border-color: oklch(0.62 0.16 145);
  box-shadow: 0 0 0 3px rgba(56, 161, 105, 0.15);
}

/* Generic validity styling for any input wired with `data-validate` (see
   validation.js). Kept separate from `.validated-input-field` so inputs can opt
   in without inheriting that component's flex/padding layout. */
[data-validate].is-invalid,
.pure-form [data-validate].is-invalid {
  border-color: oklch(0.58 0.2 25);
  border-width: 2px;
}

[data-validate].is-invalid:focus,
.pure-form [data-validate].is-invalid:focus {
  border-color: oklch(0.58 0.2 25);
  box-shadow: 0 0 0 3px rgba(229, 62, 62, 0.15);
}

[data-validate].is-valid,
.pure-form [data-validate].is-valid {
  border-color: oklch(0.62 0.16 145);
}

[data-validate].is-valid:focus,
.pure-form [data-validate].is-valid:focus {
  border-color: oklch(0.62 0.16 145);
  box-shadow: 0 0 0 3px rgba(56, 161, 105, 0.15);
}

.validated-input-error {
  display: block;
  min-height: 1.25rem;
  font-size: 0.875rem;
  color: oklch(0.58 0.2 25);
  margin-top: 0.25rem;
}

.validated-input-error:empty {
  display: none;
}

.validated-input-hint {
  margin: 0.25rem 0 0;
  font-size: 0.75rem;
  color: oklch(0.55 0.01 260);
}

/* Date input specifics */
.validated-date-input .validated-input-field {
  max-width: 200px;
}

/* Time input specifics */
.validated-time-input .validated-input-field {
  max-width: 150px;
}

/* Datetime input specifics */
.validated-datetime-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.validated-datetime-date {
  max-width: 180px;
}

.validated-datetime-time {
  max-width: 120px;
}

/* Number input specifics */
.validated-number-input .validated-input-field {
  max-width: 200px;
}

/* ================================================
   Spreadsheet Table Component
   ================================================ */
.spreadsheet-container {
  overflow: auto;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
}

.spreadsheet-table {
  border-collapse: collapse;
  table-layout: fixed;
  width: max-content;
  min-width: 100%;
}

.spreadsheet-table th,
.spreadsheet-table td {
  padding: 0;
  margin: 0;
  border: 1px solid oklch(0.85 0.008 260);
  position: relative;
}

/* Column headers */
.spreadsheet-table th {
  background: oklch(0.98 0.003 260);
  font-weight: 600;
  text-align: center;
  padding: 6px 12px;
  min-width: 100px;
  user-select: none;
  border-bottom: 2px solid oklch(0.85 0.008 260);
}

/* Row number column */
.spreadsheet-table .row-header {
  background: oklch(0.98 0.003 260);
  font-weight: 500;
  text-align: center;
  padding: 0 8px;
  min-width: 40px;
  width: 40px;
  color: oklch(0.55 0.01 260);
  user-select: none;
  border-right: 2px solid oklch(0.85 0.008 260);
}

/* Cell inputs */
.spreadsheet-cell {
  width: 100%;
  height: 100%;
  min-height: 28px;
  padding: 4px 8px;
  border: none;
  background: transparent;
  font-size: 0.9rem;
  font-family: inherit;
  box-sizing: border-box;
  outline: none;
}

.spreadsheet-cell:focus {
  background: #fff;
  box-shadow: inset 0 0 0 2px oklch(0.7 0.15 244);
}

/* Cell container for proper sizing */
.spreadsheet-table td {
  height: 28px;
  min-width: 100px;
}

/* Focused cell row/column highlight */
.spreadsheet-table tr:has(.spreadsheet-cell:focus) .row-header {
  background: oklch(0.96 0.02 250);
  color: oklch(0.52 0.2 258);
}

/* Selection state (for future multi-select) */
.spreadsheet-cell.selected {
  background: oklch(0.96 0.02 250);
}

/* Hover state for cells */
.spreadsheet-table td:hover {
  background: oklch(0.98 0.003 260);
}

.spreadsheet-table td:has(.spreadsheet-cell:focus) {
  background: transparent;
}

/* Corner cell (top-left) */
.spreadsheet-table th.corner-cell {
  min-width: 40px;
  width: 40px;
}

/* Ensure inputs fill the cell */
.spreadsheet-table td {
  position: relative;
}

.spreadsheet-cell {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

/* Readonly cells for view-only mode */
.spreadsheet-cell-readonly {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 28px;
  padding: 4px 8px;
  background: transparent;
  font-size: 0.9rem;
  font-family: inherit;
  box-sizing: border-box;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 20px;
  outline: none;
}

.spreadsheet-cell-readonly:focus {
  background: oklch(0.98 0.003 260);
  box-shadow: inset 0 0 0 1px oklch(0.85 0.008 260);
}

.spreadsheet-cell-readonly.richtext-cell {
  white-space: normal;
  overflow: auto;
}

.spreadsheet-cell.mini-richtext-editor.sheet-richtext {
  min-height: 28px;
  max-height: none;
  padding: 4px 8px;
  border: none;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  font-family: inherit;
  font-size: 0.9rem;
  line-height: 20px;
  overflow: auto;
}

.spreadsheet-cell.sheet-richtext:focus {
  border: none;
  box-shadow: inset 0 0 0 2px oklch(0.58 0.22 250);
}

.spreadsheet-cell-readonly.disabled-cell {
  background: oklch(0.98 0.003 260);
}

/* Readonly checkbox styling */
.spreadsheet-cell-readonly.spreadsheet-checkbox {
  cursor: not-allowed;
}

/* ================================================
   Sheet Data Page
   ================================================ */
.sheet-data-page {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

.sheet-data-toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  background: oklch(0.98 0.003 260);
  border-bottom: 1px solid oklch(0.89 0.006 260);
}

.sheet-data-model-label {
  font-weight: 500;
  color: oklch(0.42 0.008 260);
}

.sheet-data-model-select {
  min-width: 200px;
  padding: 0.375rem 0.75rem;
  font-size: 0.9rem;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  background-color: #fff;
}

.sheet-data-model-select:focus {
  border-color: oklch(0.7 0.15 244);
  outline: none;
  box-shadow: 0 0 0 2px rgba(74, 144, 217, 0.25);
}

.sheet-data-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 3rem;
  color: oklch(0.55 0.01 260);
  text-align: center;
}

.sheet-data-empty p {
  margin: 0.25rem 0;
}

.sheet-data-page .spreadsheet-container {
  flex: 1;
  overflow: auto;
  border: none;
  border-radius: 0;
  min-height: 0;
  /* The table sits inset from the sheet-document edges (the toolbar and
   add-row-controls above/below it stay flush). */
  padding: 0 1rem;
}

.sheet-data-page .spreadsheet-table {
  /* Fixed layout makes the <colgroup> widths authoritative: columns honour their
   set width instead of growing to fit content, and cell overflow clips. */
  table-layout: fixed;
  width: max-content;
  min-width: 100%;
}

/* Colgroup column widths. The order/kind columns are fixed; data columns default to
   160px and are overridden per-field by the persisted-width <style> block. */
.sheet-data-page .spreadsheet-table col.order-col {
  width: 44px;
}

.sheet-data-page .spreadsheet-table col.kind-col {
  width: 80px;
}

.sheet-data-page .spreadsheet-table col.sheet-data-col {
  width: 160px;
}

/* Clip cell content to its (now fixed-width) column so long values don't hang out.
   Drop the auto-layout min-width that would otherwise fight the fixed widths. */
.sheet-data-page .spreadsheet-table td {
  overflow: hidden;
  min-width: 0;
}

/* Cells that host a popover (the Options dropdown and the row-menu dropdown) must
   never clip it — the dropdown extends below the cell, and clipping it would swallow
   clicks on its lower items. These stay overflow:visible regardless of focus. */
.sheet-data-page .spreadsheet-table td.order-cell,
.sheet-data-page .spreadsheet-table td:has(.options-cell-wrapper) {
  overflow: visible;
}

/* Column header styling for data table */
.sheet-data-page .spreadsheet-table th {
  text-align: left;
  vertical-align: top;
  /* Override the auto-layout 100px floor so columns can shrink to MIN_COL_WIDTH. */
  min-width: 0;
}

/* Resize handle on a data column header's right edge. Straddles the border so it's
   easy to grab; sits above the header content. JS (.col-resize-handle) drives the drag. */
.sheet-data-page .spreadsheet-table th .col-resize-handle {
  position: absolute;
  top: 0;
  right: -3px;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 6;
  touch-action: none;
  user-select: none;
}

.sheet-data-page .spreadsheet-table th .col-resize-handle:hover,
.sheet-data-page .spreadsheet-table th .col-resize-handle.resizing {
  background: rgba(74, 144, 217, 0.4);
}

/* Focus reveal: when the focused cell's content overflows its column, it shows the
   full content as an overlay popover, overflowing neighbours via a raised z-index
   without disturbing layout. The td always allows overflow on focus; the actual
   reveal styling is gated by the `.cell-revealed` class, which sheetData.js toggles
   only when overflow is detected (CSS alone can't measure overflow), so non-overflowing
   cells look unchanged during normal editing. Non-input cells size to content via
   max-content; <input> cells are sized to fit by JS (inputs ignore max-content). */
.sheet-data-page .spreadsheet-table td:focus-within {
  overflow: visible;
  z-index: 5;
}

.sheet-data-page .spreadsheet-table .spreadsheet-cell.cell-revealed,
.sheet-data-page .spreadsheet-table .spreadsheet-cell-readonly.cell-revealed {
  right: auto;
  width: max-content;
  min-width: 100%;
  max-width: 480px;
  overflow: visible;
  white-space: nowrap;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
  z-index: 5;
}

.sheet-data-page .spreadsheet-table th.kind-column {
  min-width: 80px;
  width: 80px;
  font-weight: 600;
  text-align: center;
  background: oklch(0.93 0.005 260);
  border-right: 2px solid oklch(0.85 0.008 260);
}

.sheet-data-page .column-header {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: space-between;
  gap: 4px;
  min-width: 0;
}

.sheet-data-page .column-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}

.sheet-data-page .column-name {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sheet-data-page .column-source {
  font-weight: 400;
  font-size: 0.75em;
  font-style: italic;
  color: oklch(0.63 0.012 260);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Column sort button */
.column-sort-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 4px;
  font-size: 0.75rem;
  color: oklch(0.75 0.01 260);
  vertical-align: middle;
  margin-left: 4px;
}

.column-sort-btn:hover {
  color: oklch(0.42 0.008 260);
}

.column-sort-btn[data-current=asc],
.column-sort-btn[data-current=desc] {
  color: oklch(0.7 0.15 244);
}

/* Sort chips container (inline with toolbar) */
.sheet-sort-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-left: 1rem;
  align-items: center;
}

.sheet-sort-chips:empty {
  display: none;
}

.sheet-data-no-rows {
  text-align: center;
  color: oklch(0.55 0.01 260);
  font-style: italic;
  padding: 2rem !important;
}

/* Kind column in data rows */
.sheet-data-page td.kind-column,
.sheet-data-page td.kind-cell {
  text-align: center;
  background: oklch(0.98 0.003 260);
  font-size: 0.85rem;
  color: oklch(0.42 0.008 260);
  border-right: 2px solid oklch(0.85 0.008 260);
  padding: 0 8px;
}

/* Disabled cells (non-applicable fields) */
.spreadsheet-cell.disabled-cell {
  background: oklch(0.98 0.003 260);
  color: oklch(0.75 0.01 260);
  cursor: default;
}

.spreadsheet-cell.disabled-cell:focus {
  box-shadow: inset 0 0 0 2px oklch(0.7 0.15 244);
  background: oklch(0.93 0.005 260);
}

/* Invalid cells (value could not be parsed for the field type) */
.spreadsheet-cell.invalid-cell {
  border: 2px solid oklch(0.58 0.2 25);
  background: oklch(0.97 0.012 25);
}

.spreadsheet-cell.invalid-cell:focus {
  box-shadow: inset 0 0 0 2px oklch(0.58 0.2 25);
}

/* Options cell wrapper and searchable dropdown */
.options-cell-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.options-cell-trigger {
  width: 100%;
  height: 100%;
  padding: 0 0.5rem;
  border: none;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  text-align: left;
  font-size: inherit;
  font-family: inherit;
}

.options-cell-trigger:focus {
  background: #fff;
  box-shadow: inset 0 0 0 2px oklch(0.7 0.15 244);
  outline: none;
}

.options-cell-value {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.options-cell-placeholder {
  color: oklch(0.75 0.01 260);
  font-style: italic;
}

.options-cell-arrow {
  color: oklch(0.55 0.01 260);
  font-size: 0.75rem;
  margin-left: 0.25rem;
  flex-shrink: 0;
}

.options-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  min-width: 150px;
  max-height: 200px;
  background: #fff;
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: 1000;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.options-dropdown.dropdown-above {
  top: auto;
  bottom: 100%;
}

.options-dropdown-search {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: none;
  border-bottom: 1px solid oklch(0.93 0.005 260);
  font-size: 0.875rem;
  outline: none;
}

.options-dropdown-search:focus {
  background: oklch(0.98 0.003 260);
}

.options-dropdown-list {
  overflow-y: auto;
  max-height: 160px;
}

.options-dropdown-item {
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  font-size: 0.875rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.options-dropdown-item:hover,
.options-dropdown-item.highlighted {
  background: oklch(0.93 0.005 260);
}

.options-dropdown-item.selected {
  background: oklch(0.96 0.02 250);
  font-weight: 500;
}

.options-dropdown-item.selected:hover,
.options-dropdown-item.selected.highlighted {
  background: oklch(0.96 0.02 250);
}

.options-clear-text {
  color: oklch(0.55 0.01 260);
  font-style: italic;
}

/* Person dropdown items stack the display name over a muted email meta line. */
.person-dropdown-item {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  white-space: normal;
}

.person-dropdown-item .person-name {
  font-size: 0.875rem;
}

.person-dropdown-item .person-email {
  font-size: 0.75rem;
  color: oklch(0.55 0.01 260);
}

/* Cell container for spreadsheet */
.spreadsheet-cell-td {
  position: relative;
  height: 28px;
  min-width: 100px;
  padding: 0;
}

/* Checkbox cells */
.spreadsheet-checkbox {
  width: 18px;
  height: 18px;
  margin: auto;
  display: block;
  cursor: pointer;
  /* Reset default checkbox appearance for consistent styling */
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  border: 2px solid oklch(0.75 0.01 260);
  border-radius: 3px;
  background: #fff;
  position: relative;
}

.spreadsheet-checkbox:checked {
  background: oklch(0.7 0.15 244);
  border-color: oklch(0.7 0.15 244);
}

.spreadsheet-checkbox:checked::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 1px;
  width: 5px;
  height: 10px;
  border: solid white;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.spreadsheet-checkbox:focus {
  outline: 2px solid oklch(0.7 0.15 244);
  outline-offset: 2px;
}

/* Add Row Controls */
.add-row-controls {
  padding: 0.75rem 1rem;
  background: oklch(0.98 0.003 260);
  border-top: 1px solid oklch(0.89 0.006 260);
}

.add-row-button {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
  color: oklch(0.42 0.008 260);
  background: #fff;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.15s, border-color 0.15s;
}

.add-row-button:hover {
  background: oklch(0.93 0.005 260);
  border-color: oklch(0.75 0.01 260);
}

.add-row-button:active {
  background: oklch(0.89 0.006 260);
}

.add-row-dropdown {
  position: relative;
  display: inline-block;
}

.add-row-menu {
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 200px;
  width: max-content;
  max-height: 300px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 4px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  margin-top: 4px;
  z-index: 1000;
}

.add-row-menu.dropdown-above {
  top: auto;
  bottom: 100%;
  margin-top: 0;
  margin-bottom: 4px;
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.15);
}

.add-row-menu .dropdown-search {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: none;
  border-bottom: 1px solid oklch(0.89 0.006 260);
  font-size: 0.9rem;
}

.add-row-menu .dropdown-search:focus {
  outline: none;
  background: oklch(0.98 0.003 260);
}

.add-row-menu .dropdown-options {
  max-height: 220px;
  overflow-y: auto;
}

.add-row-menu .dropdown-option {
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  font-size: 0.9rem;
  white-space: nowrap;
}

.add-row-menu .dropdown-option:hover {
  background: oklch(0.93 0.005 260);
}

.add-row-menu .dropdown-option:active {
  background: oklch(0.89 0.006 260);
}

/* =============================================================================
   Utility Classes (replacing inline styles per audit)
   ============================================================================= */
.app-error-margin {
  margin: 2em;
}

/* The /app landing page. Owns the page gutter directly instead of borrowing
   `.app-error-margin`, which is a utility the invite pages also use. */
.app-home {
  margin: 2em;
}

/* The landing page's widget grid uses the shared `.widget-columns` layout. The
   cap keeps two columns at a readable line length on a wide window; the shared
   `auto-fit` rule drops them to one column below 2 * 22rem + gap. */
.app-home .widget-columns {
  max-width: 80rem;
  margin: 1.5rem 0;
}

.app-logo-centered {
  display: block;
  margin: 0 auto;
}

.full-width {
  width: 100%;
}

.input-width-sm {
  width: 120px;
}

.select-auto-inline {
  width: auto;
  margin-left: 0.5em;
}

.share-modal-new {
  color: oklch(0.35 0.1 145);
}

/* =========================================================================
   Saved Sheet Views — chip bar + New View modal
   ========================================================================= */
.sheet-view-chips {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-left: 0.75rem;
}

.sheet-view-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.6rem;
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.3 0.006 260);
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 12px;
  font-size: 0.8rem;
  cursor: pointer;
  line-height: 1.4;
}

.sheet-view-chip:hover {
  background-color: oklch(0.89 0.006 260);
}

.sheet-view-chip.sheet-view-default {
  font-weight: 600;
}

.sheet-view-chip.sheet-view-add {
  background-color: transparent;
  border-style: dashed;
  color: oklch(0.7 0.15 244);
}

.sheet-view-chip.sheet-view-add:hover {
  background-color: oklch(0.96 0.02 250);
}

/* Delete affordance lives inside a deletable (sheet-owned) view chip. */
.sheet-view-chip .chip-remove {
  color: oklch(0.63 0.012 260);
  cursor: pointer;
  padding: 0 0.1rem;
  font-size: 1rem;
  line-height: 1;
  border-radius: 50%;
}

.sheet-view-chip .chip-remove:hover {
  color: oklch(0.62 0.2 27);
}

/* New View + Edit View + Delete View modals: hidden until data-visible (matches the
   other modals, since .modal-backdrop itself defaults to display:flex). */
#new-view-modal,
#edit-view-modal,
#delete-view-modal {
  display: none;
}

#new-view-modal[data-visible=true],
#edit-view-modal[data-visible=true],
#delete-view-modal[data-visible=true] {
  display: flex;
}

/* The inline error only occupies space once it has a message. */
#new-view-error:empty,
#edit-view-error:empty {
  display: none;
}

/* Shared warning line (e.g. editing/deleting a template-owned, shared view). */
.form-warning {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0;
  padding: 0.5rem 0.75rem;
  border: 1px solid transparent;
  font-size: 0.9rem;
  border-radius: 4px;
  padding: 0.75rem 1rem;
  background-color: oklch(0.97 0.055 92);
  border-color: oklch(0.85 0.17 90);
  color: oklch(0.5 0.11 78);
}

/* Stack each field's label above its control, and let the name input span the
   modal width like the description box (both fields share .form-field's margin). */
#new-view-form > .form-field > label,
#edit-view-modal .form-field > label {
  display: block;
  margin-bottom: 0.25rem;
}

#new-view-form input[type=text],
#edit-view-modal input[type=text] {
  display: block;
  width: 100%;
  box-sizing: border-box;
}

/* New View modal: scope radio + the mini rich-text description editor. */
.new-view-scope {
  border: none;
  padding: 0;
  margin: 0.5rem 0;
}

.new-view-scope legend {
  font-size: 0.85rem;
  color: oklch(0.55 0.01 260);
  padding: 0;
  margin-bottom: 0.25rem;
}

.new-view-scope-option {
  display: block;
  font-weight: normal;
  margin: 0.15rem 0;
}

/* Mini (b/i/u/s) editor used for the View description — short, unlike the
   full-height document editor it inherits from. */
.text-editor.mini-richtext-editor {
  min-height: 5rem;
  max-height: 12rem;
  font-family: inherit;
  font-size: 0.9rem;
  padding: 0.5rem;
}

/* ---- Views management tab ------------------------------------------------- */
.sheet-views-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.75rem 1.5rem;
  max-width: 48rem;
}

/* Forms tab: content is loaded lazily into this mount, so put the
   horizontal inset on the mount itself (matches Models/Views padding). */
#forms-tab-loader {
  padding: 1rem 1.5rem;
}

.sheet-views-empty {
  color: oklch(0.55 0.01 260);
  font-style: italic;
}

.sheet-view-card {
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 6px;
  padding: 0.75rem 1rem;
  background-color: #fff;
}

.sheet-view-card-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.sheet-view-card-title {
  margin: 0;
  font-size: 1.05rem;
  flex: 1 1 auto;
}

.sheet-view-template-badge {
  flex: 0 0 auto;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: oklch(0.55 0.01 260);
  background-color: oklch(0.93 0.005 260);
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 10px;
  padding: 0.05rem 0.5rem;
}

/* Compact kebab trigger inside a view card (overrides the default button look). */
.sheet-view-card .dropdown {
  flex: 0 0 auto;
}

.sheet-view-card .dropdown-trigger {
  padding: 0.1rem 0.5rem;
  line-height: 1;
  font-size: 1.1rem;
  background: transparent;
  border: none;
  box-shadow: none;
  color: oklch(0.55 0.01 260);
}

.sheet-view-card .dropdown-trigger:hover {
  background-color: oklch(0.93 0.005 260);
}

.sheet-view-card-description {
  margin: 0.4rem 0 0;
  color: oklch(0.3 0.006 260);
  font-size: 0.9rem;
  /* Description is canonical rich text: newlines are stored as "\n", so render
   them as line breaks (matching the read-only plaintext rich-text view). */
  white-space: pre-wrap;
  word-wrap: break-word;
  overflow-wrap: break-word;
}

.sheet-view-card-summary {
  margin-top: 0.5rem;
}

.sheet-view-summary-line {
  margin: 0.15rem 0;
  color: oklch(0.55 0.01 260);
  font-size: 0.85rem;
}

.sheet-view-sort-key {
  white-space: nowrap;
}

.sheet-view-card-footer {
  margin-top: 0.6rem;
}

/* Link-styled button: opens the view on the Data tab (own line). */
.sheet-view-open-link {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 0.85rem;
  color: oklch(0.7 0.15 244);
  cursor: pointer;
}

.sheet-view-open-link:hover {
  color: oklch(0.52 0.2 258);
  text-decoration: underline;
}

/* ============================================================================
   Sheet-based Forms — public form page + editor Forms tab
   ============================================================================ */
/* Public form page (/f/{slug}) */
.public-form {
  max-width: 640px;
  margin: 2rem auto;
  padding: 0 1rem;
}

/* Google reCAPTCHA widget spacing (registration + public forms). Google styles
   the checkbox iframe itself; we only own the margin around it. */
.recaptcha-widget {
  margin: 1rem 0;
}

.public-form .form-title {
  margin-bottom: 0.5rem;
}

.public-form .form-description {
  margin-bottom: 1rem;
  color: oklch(0.55 0.01 260);
}

.public-form .form-section {
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 6px;
  padding: 1rem;
  margin-bottom: 1rem;
}

.public-form .form-section legend {
  font-weight: 600;
  padding: 0 0.4rem;
}

.public-form .form-field {
  margin-bottom: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.public-form .form-field-label {
  font-weight: 600;
}

.public-form .form-field .required-marker {
  color: oklch(0.58 0.2 25);
}

.public-form .form-control {
  width: 100%;
  box-sizing: border-box;
  padding: 0.4rem 0.5rem;
}

.public-form .form-field-help {
  font-size: 0.85em;
  color: oklch(0.55 0.01 260);
  margin: 0;
}

.public-form .form-field.has-error .form-control {
  border-color: oklch(0.58 0.2 25);
  border-width: 2px;
}

/* Error message text under a field. Empty (no text) when the field is valid, so
   it takes no space; the client validator (validation.ts) or a submit failure
   fills it. Inline `.is-invalid`/`.is-valid` borders come from the generic
   `[data-validate]` rules above. */
.public-form .form-field-error {
  color: oklch(0.58 0.2 25);
  font-size: 0.85em;
  margin: 0;
}

.public-form .form-submit {
  margin-top: 0.5rem;
}

/* Honeypot: present in the DOM, invisible to humans, off the tab order. */
.form-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-thank-you,
.form-closed {
  max-width: 640px;
  margin: 3rem auto;
  padding: 0 1rem;
  text-align: center;
}

/* Editor Forms tab */
.forms-tab .forms-create {
  margin-bottom: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  align-items: flex-start;
}

.forms-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.form-row {
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 6px;
  padding: 0.6rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.form-row-main {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem;
}

.form-row-title {
  font-weight: 600;
}

.form-row-model {
  color: oklch(0.55 0.01 260);
  font-size: 0.9em;
}

.form-row-link {
  font-family: monospace;
}

/* The kebab "⋯" menu sits at the right end of the card's top row. */
.form-row-menu {
  margin-left: auto;
}

/* Response count is its own (second) row now, so no right-push. */
.form-row-count {
  color: oklch(0.55 0.01 260);
  font-size: 0.85em;
}

.form-row-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}

.form-delete-button {
  margin-left: auto;
}

/* ── Forms builder (Phase 4) ─────────────────────────────────────────────── */
.forms-builder {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.forms-builder-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.forms-builder-bar .form-row-link {
  margin-left: auto;
}

.builder-meta,
.builder-add-section,
.builder-add-field {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: flex-start;
}

.builder-add-section {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

.builder-label {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.9em;
  color: oklch(0.55 0.01 260);
  width: 100%;
  max-width: 32rem;
}

/* Inside a field card the labels sit inline (text beside the input) and each
   takes the full row width, so its input can grow across the whole card. */
.builder-field-form .builder-label {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  max-width: none;
}

.builder-field-form .builder-label .form-control {
  flex: 1 1 auto;
  min-width: 0;
}

.builder-inline {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.9em;
  margin-right: 0.75rem;
}

.builder-num {
  width: 6rem;
}

.builder-sections {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.builder-section {
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 6px;
  padding: 0.75rem;
  margin: 0;
}

/* Builder rows double as `.single-list-row` (for drag reorder), which is a
   horizontal flex. Override to stack vertically so the head (grip/title/menu)
   sits on top and its content (fields / presentation form) flows underneath,
   rather than head-left / content-right. */
.builder-section.single-list-row,
.builder-field.single-list-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.builder-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  border-bottom: 1px solid oklch(0.89 0.006 260);
  padding-bottom: 0.5rem;
  margin-bottom: 0.5rem;
}

.builder-section-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  flex: 1 1 auto;
}

.builder-section-title {
  font-weight: 600;
  min-width: 10rem;
}

.builder-section-desc {
  min-width: 14rem;
  flex: 1 1 auto;
}

.builder-section-actions,
.builder-field-actions {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.builder-fields {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.builder-field {
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 6px;
  padding: 0.6rem;
  background: oklch(0.98 0.003 260);
  /* Extra breathing room before the next field's name. */
  margin-bottom: 0.75rem;
}

.builder-field-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}

.builder-field-name {
  font-weight: 600;
}

.builder-field-kind {
  font-size: 0.8em;
  color: oklch(0.55 0.01 260);
  border: 1px solid oklch(0.85 0.008 260);
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
}

.builder-field-pi {
  font-size: 0.8em;
  color: oklch(0.53 0.22 300);
}

.builder-field-actions {
  margin-left: auto;
}

.builder-field-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.6rem;
}

.builder-constraints {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
}

.builder-variants {
  flex-direction: row;
}

.builder-field-userref {
  font-style: italic;
}

.builder-section-empty {
  margin: 0.25rem 0;
}

/* ── Forms phase-4 revision: public form clusters + builder + data tab ─────── */
/* PersonalInfo cluster on the public form. */
.public-form .form-personal-info {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

/* Given + family name side-by-side; collapses to one column on narrow screens. */
.public-form .form-name-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
}

@media (max-width: 30rem) {
  .public-form .form-name-row {
    grid-template-columns: 1fr;
  }
}
/* The "My family name comes first" toggle reads as a lesser, secondary line. */
.public-form .form-field-reversed {
  margin-top: -0.15rem;
}

.public-form .form-field-label-subtle {
  color: oklch(0.55 0.01 260);
  font-size: 0.9em;
  font-weight: 400;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

/* Access & entries block in the form builder. */
.builder-settings {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
  padding: 0.5rem 0;
}

/* Submitter cell on the Data tab: a profile link, never a raw UUID. */
.submitter-link {
  color: oklch(0.52 0.2 258);
  text-decoration: none;
}

.submitter-link:hover {
  text-decoration: underline;
}

.submitter-anon {
  color: oklch(0.63 0.012 260);
  font-style: italic;
}

/* Forms/PersonalInfo confirmation modals use dynamic ids, so they hide via a
   class (not an id rule). `.modal-backdrop` defaults to display:flex, so without
   this the hidden modal overlays the page and intercepts clicks. */
.modal-backdrop.confirm-modal {
  display: none;
}

.modal-backdrop.confirm-modal[data-visible=true] {
  display: flex;
}

/* Form QR modal: the scannable code plus its full URL. The code keeps a white
   plate in every theme, because a QR needs light modules under dark ones to
   scan — inverting it would break the camera, not just the look. */
.form-qr-image {
  display: flex;
  justify-content: center;
  background-color: #fff;
  padding: 1rem;
  margin-bottom: 1rem;
  border-radius: 8px;
}

.form-qr-image svg {
  display: block;
  width: 100%;
  max-width: 240px;
  height: auto;
}

.form-qr-url {
  font-family: var(--font-monospace);
  font-size: 0.85rem;
  word-break: break-all;
  text-align: center;
  color: oklch(0.42 0.008 260);
  user-select: all;
}

/* Rich-text form field: a contenteditable mini editor styled like an input. */
/* Mini rich-text editor box (public forms + the profile edit page's Bio field).
   Both give the contenteditable a visible input-like frame. */
.public-form .form-richtext,
.edit-profile-page .form-richtext {
  min-height: 4.5rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  cursor: text;
  background-color: #fff;
  border: 1px solid oklch(0.24 0.006 260);
  border-radius: 4px;
  resize: vertical;
  overflow: auto;
}

/* Forms builder field drag-reorder (single-list rows). */
.builder-fields-list .single-list-rows {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.builder-field-grip {
  cursor: grab;
  color: oklch(0.63 0.012 260);
  user-select: none;
}

.builder-field-grip:active {
  cursor: grabbing;
}

/* Forms builder: section drag-reorder + droppable empty field zones. */
.builder-sections-list .single-list-rows {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.builder-section-grip {
  cursor: grab;
  color: oklch(0.63 0.012 260);
  user-select: none;
  margin-right: 0.4rem;
}

.builder-section-grip:active {
  cursor: grabbing;
}

/* Keep an empty section's field list droppable. */
.builder-fields-list .single-list-rows {
  min-height: 1.6rem;
}

/* ===========================================================================
   Form Wizard (Phase 5) — guided create flow hosted on the Sheet.
   =========================================================================== */
.form-wizard {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Step rail: numbered Model → Layout → Preview → Access. */
.wizard-rail {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
  border-bottom: 1px solid oklch(0.93 0.005 260);
  padding-bottom: 0.75rem;
}

.wizard-rail-step {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: oklch(0.63 0.012 260);
  font-weight: 500;
}

.wizard-rail-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 999px;
  border: 1px solid oklch(0.85 0.008 260);
  background: #fff;
  font-size: 0.85em;
}

.wizard-rail-step.current {
  color: oklch(0.24 0.006 260);
}

.wizard-rail-step.current .wizard-rail-index {
  border-color: oklch(0.52 0.2 258);
  background: oklch(0.52 0.2 258);
  color: #fff;
}

.wizard-rail-step.done {
  color: oklch(0.55 0.01 260);
}

.wizard-rail-step.done .wizard-rail-index {
  border-color: oklch(0.52 0.2 258);
  color: oklch(0.52 0.2 258);
}

.wizard-body {
  min-height: 8rem;
}

.wizard-step-intro h2 {
  margin: 0 0 0.25rem;
}

.wizard-step-intro .hint {
  margin: 0 0 1rem;
}

/* Footer: Back on the left, Exit + Next/Finish on the right. */
.wizard-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  border-top: 1px solid oklch(0.93 0.005 260);
  padding-top: 0.75rem;
}

.wizard-footer-right {
  display: flex;
  gap: 0.5rem;
}

/* Step-1 sample preview controls + mount. */
.wizard-preview-controls {
  margin-top: 1rem;
}

.wizard-preview-mount:not(:empty) {
  margin-top: 1rem;
}

/* Non-interactive form preview (Wizard steps 1 & 3). */
.form-preview {
  border: 1px solid oklch(0.89 0.006 260);
  border-radius: 8px;
  padding: 1rem 1.25rem;
  background: oklch(0.98 0.003 260);
}

.form-preview-caption {
  margin: 0 0 0.75rem;
  font-size: 0.85em;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: oklch(0.63 0.012 260);
}

/* The preview body reuses .public-form styling but is display-only. */
.form-preview-body {
  pointer-events: none;
}

/* Step 3 shows the blank and sample-filled previews side by side (stacking on
   narrow viewports). */
.wizard-preview-pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: 1rem;
}

/* =============================================================================
   Invite Modal + Invite accept page
   ============================================================================= */
.invite-modal {
  width: 90%;
  max-width: 640px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.invite-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.invite-modal-header h2 {
  margin-bottom: 0;
}

.modal-close {
  background: none;
  border: none;
  font-size: 1.75rem;
  line-height: 1;
  cursor: pointer;
  color: oklch(0.63 0.012 260);
  padding: 0 0.25rem;
}

.modal-close:hover {
  color: oklch(0.24 0.006 260);
}

/* Reuse the .public-form *field* styles (full-width inputs, labels above) but drop
   its page-container styles — inside the modal the form fills the available width. */
.invite-add-form.public-form {
  max-width: none;
  margin: 0;
  padding: 0;
}

/* Inline error for the add-person form (filled by the hx-on error handler). Empty
   when valid, so it takes no space. */
#invite-add-error:empty {
  display: none;
}

#invite-add-error {
  margin: 0 0 0.5rem;
}

/* Project People page: every row also carries its group chips, so the row is a
   flex line here. Scoped to this list — the /app/users index has one child per
   row and keeps the plain block layout. */
#project-people-list .user-item,
.person-group-list .user-item {
  display: flex;
  align-items: center;
}

#project-people-list .user-link,
.person-group-list .user-link {
  flex: 1 1 auto;
  min-width: 0;
}

/* Project People page: an outstanding-invite row reads like a member row, so
   its static link behaves like the member row's anchor. */
.user-item-invite {
  display: flex;
  align-items: center;
}

.user-item-invite .user-link-static {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 0.5rem;
  cursor: default;
  flex: 1;
  min-width: 0;
}

/* The ⋯ cell at the end of a People row.
   Fixed width, and rendered even when the row has no actions, so the group
   column beside it starts at the same x on every row — a member row and an
   invitee row offer different actions, and used to be different widths. */
.person-row-menu {
  flex: 0 0 2.5rem;
  display: flex;
  justify-content: flex-end;
  padding-right: 0.5rem;
}

/* A bare glyph rather than a button, matching the calendar's event menu.
   Scoped, because `dropdown_menu` gives every trigger `pure-button` and the
   other thirty-odd callers want that. */
#project-people-list .dropdown-trigger,
.person-group-list .dropdown-trigger {
  background: none;
  border: none;
  box-shadow: none;
  font-size: 1.25rem;
  line-height: 1;
  padding: 0.25rem 0.4rem;
  cursor: pointer;
  color: oklch(0.55 0.01 260);
  border-radius: 4px;
}

#project-people-list .dropdown-trigger:hover,
.person-group-list .dropdown-trigger:hover {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.3 0.006 260);
}

/* Status badge shown on invitee (and used inside the People meta line). */
.invite-status {
  border-radius: 8px;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.1rem 0.4rem;
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.invite-status-member {
  background-color: oklch(0.92 0.045 145);
  color: oklch(0.62 0.16 145);
}

.invite-status-pending {
  background-color: oklch(0.97 0.075 92);
  color: oklch(0.5 0.11 78);
}

.invite-status-accepted {
  background-color: oklch(0.92 0.045 145);
  color: oklch(0.62 0.16 145);
}

.invite-status-declined {
  background-color: oklch(0.9 0.045 20);
  color: oklch(0.62 0.2 27);
}

.invite-status-expired {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

/* Invite accept page (/app/invite/{slug}) */
.invite-card {
  border-radius: 8px;
  max-width: 32rem;
  margin: 2rem auto;
  padding: 1.5rem;
  border: 1px solid oklch(0.93 0.005 260);
}

.invite-actions {
  display: flex;
  gap: 0.75rem;
  margin-top: 1rem;
}

.casting-demographics-section {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 250ms ease;
  margin-top: 1rem;
}

.casting-demographics-section[data-open=false] {
  grid-template-rows: 0fr;
  margin-top: 0;
}

.casting-demographics-inner {
  overflow: hidden;
  min-height: 0;
}

.demographics-fields {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows 200ms ease;
  margin-top: 0.5rem;
}

.demographics-fields[data-open=false] {
  grid-template-rows: 0fr;
  margin-top: 0;
}

.demographics-fields-inner {
  overflow: hidden;
  min-height: 0;
}

@media (prefers-reduced-motion: reduce) {
  .casting-demographics-section,
.demographics-fields {
    transition: none;
  }
}
.demographics-subgroup {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid oklch(0.93 0.005 260);
}

.demographics-subgroup:first-of-type {
  border-top: none;
  padding-top: 0;
}

.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  margin: 0.25rem 0 0.75rem;
}

.checkbox-group label {
  margin: 0;
}

.playable-age-range {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.playable-age-range input[type=number] {
  width: 5rem;
}

.demographics-inline-list {
  margin: 0.25rem 0;
  padding-left: 1.25rem;
}

.profile-demographics {
  margin-top: 1.5rem;
}

.demographics-list dt {
  font-weight: bold;
  margin-top: 0.5rem;
}

.demographics-list dd {
  margin: 0 0 0.25rem 0;
}

.profile-demographics .demographics-list dt {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: oklch(0.55 0.01 260);
  margin-top: 0.75rem;
}
.profile-demographics .demographics-list dt:first-child {
  margin-top: 0;
}
.profile-demographics .demographics-list dd {
  font-size: 1.1rem;
  font-weight: normal;
  line-height: 1.35;
  color: oklch(0.24 0.006 260);
  margin: 0.15rem 0 0 0;
}
.profile-demographics .demographics-inline-list {
  font-size: 1.05rem;
}

/* ----------------------------------------------------------------------------
   Call sheet (calendar event page)

   Everyone in the production, for one occurrence: who, when they are called,
   when they arrived, when they left. Built on the shared spreadsheet-table
   convention so arrow keys walk the three controls.
   ------------------------------------------------------------------------- */
.calendar-call-sheet {
  margin-top: 1.5rem;
}

.calendar-call-sheet .spreadsheet-table {
  table-layout: fixed;
  width: max-content;
  min-width: 100%;
}

.calendar-call-sheet .spreadsheet-table th {
  text-align: left;
  min-width: 0;
}

.calendar-call-sheet .spreadsheet-table td {
  overflow: hidden;
  min-width: 0;
  padding: 0.25rem 0.5rem;
}

/* The name is the column a stage manager reads, so it gets the room. */
.calendar-call-sheet col.call-sheet-col-person {
  width: 260px;
}

.calendar-call-sheet col.call-sheet-col-time {
  width: 150px;
}

.calendar-call-sheet col.call-sheet-col-check {
  width: 180px;
}

/* An occurrence that crosses midnight needs the date in its controls, and a
   datetime-local control is much wider than a time one. */
.calendar-call-sheet .call-sheet-table-datetime col.call-sheet-col-time {
  width: 210px;
}

.calendar-call-sheet .call-sheet-table-datetime col.call-sheet-col-check {
  width: 240px;
}

/* The shared .spreadsheet-cell is absolutely positioned so one input fills its
   td. A check cell holds an input beside a remove button, so this table lays
   its cells out normally instead. */
.calendar-call-sheet .spreadsheet-cell {
  position: static;
  width: 100%;
}

.calendar-call-sheet .call-sheet-check-set {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.calendar-call-sheet .call-sheet-check-set .spreadsheet-cell {
  width: auto;
  flex: 1 1 auto;
  min-width: 0;
}

.calendar-call-sheet .call-sheet-clear {
  border-radius: 4px;
  flex: 0 0 auto;
  background: none;
  border: 1px solid oklch(0.85 0.008 260);
  color: oklch(0.55 0.01 260);
  cursor: pointer;
  line-height: 1;
  padding: 0.1rem 0.35rem;
}

.calendar-call-sheet .call-sheet-clear:hover {
  background-color: oklch(0.9 0.045 20);
  color: oklch(0.62 0.2 27);
}

.calendar-call-sheet .call-sheet-person {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.calendar-call-sheet .call-sheet-person-name {
  color: oklch(0.42 0.008 260);
}

/* The state chip, in the shape .invite-status already uses. */
.call-state {
  border-radius: 8px;
  flex: 0 0 auto;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.1rem 0.4rem;
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.42 0.008 260);
}

.call-state-called {
  background-color: oklch(0.92 0.045 145);
  color: oklch(0.62 0.16 145);
}

.call-state-optional {
  background-color: oklch(0.96 0.02 250);
  color: oklch(0.52 0.2 258);
}

.call-state-excused {
  background-color: oklch(0.97 0.075 92);
  color: oklch(0.5 0.11 78);
}

.call-state-not-called {
  background-color: oklch(0.93 0.005 260);
  color: oklch(0.55 0.01 260);
}

/* Not called and Excused sit in the call time column, in place of the control
   they do not get. They fill the cell rather than hugging the text, so the
   column still reads as a column. */
.calendar-call-sheet .call-sheet-call-time-cell .call-state {
  display: inline-block;
  width: 100%;
  text-align: center;
}

/* A group is a subject on the sheet, not a heading over one, so it reads as one
   line among the people. The weight is the only thing that says it names more
   than one person. */
.calendar-call-sheet .call-sheet-group-name {
  font-weight: 600;
}

.calendar-call-sheet .call-sheet-group-name::before {
  content: "☉ ";
  color: oklch(0.55 0.01 260);
  font-weight: 400;
}

/* A row nobody called is still listed, but it should not compete for
   attention with the people who have to be there. */
.calendar-call-sheet .call-sheet-row-not-called .call-sheet-person-link,
.calendar-call-sheet .call-sheet-row-not-called .call-sheet-person-name {
  color: oklch(0.55 0.01 260);
}
