﻿:root {
  --brand-ink: var(--c21-digital-black, #121212);
  --brand-ink-soft: var(--c21-obsessed-grey, #252526);
  --brand-gold: var(--c21-legacy-gold, #FFC72C);
  --brand-grey: var(--c21-medium-grey, #808285);
  --brand-grey-light: var(--c21-light-grey, #E6E7E8);
  /* Hover accent for clickable icons/links - a warm gold, deliberately never
     the same near-black as body text, so a hovered control never looks like
     it just turned into plain (or disabled) text. */
  --brand-hover: var(--c21-dark-gold, #A19276);
  --brand-hover-bg: rgba(255, 199, 44, 0.18);
}

body {
  font-family: "Typold", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 1.5rem 3rem;
  color: var(--brand-ink);
}

h1, h2, h3 {
  font-family: "Typold Condensed", "Typold", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-weight: 800;
}

nav {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 1.25rem 0;
  margin-bottom: 1.5rem;
  border-bottom: 3px solid var(--brand-gold);
}

nav .brand-mark {
  margin-right: 0.5rem;
  line-height: 0;
}

nav .nav-logo {
  height: 28px;
  width: auto;
  display: block;
}

nav a {
  font-weight: 600;
  text-decoration: none;
  color: var(--brand-ink);
  padding-bottom: 0.2rem;
  border-bottom: 2px solid transparent;
}

nav a:hover {
  border-bottom-color: var(--brand-gold);
}

form label {
  display: block;
  margin-bottom: 0.75rem;
}

form input, form textarea, form select {
  display: block;
  width: 100%;
  padding: 0.5rem;
  margin-top: 0.25rem;
  box-sizing: border-box;
  font-family: inherit;
}

form textarea {
  min-height: 4rem;
  font-family: monospace;
}

button {
  padding: 0.5rem 1rem;
  background: var(--brand-ink);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-family: inherit;
}

button:hover {
  background: var(--brand-ink-soft);
}

/* Icon buttons (Heroicons via _icons.html) - a deliberately generous click
   target and a strong neutral-vs-danger color split, so Edit and Delete
   read as two different actions instead of two buttons that happen to sit
   next to each other. */
.hi {
  display: block;
  flex-shrink: 0;
}

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--brand-grey);
  cursor: pointer;
  text-decoration: none;
}

.icon-btn:hover {
  background: var(--brand-hover-bg);
  color: var(--brand-hover);
}

.icon-btn-danger:hover {
  background: #fee2e2;
  color: #dc2626;
}

h2 button, h3 button {
  font-size: 0.85rem;
  padding: 0.3rem 0.7rem;
  margin-left: 0.75rem;
  vertical-align: middle;
}

table .gen-individual {
  font-size: 0.8rem;
  padding: 0.25rem 0.6rem;
}

table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1.5rem;
}

th, td {
  text-align: left;
  padding: 0.5rem;
  border-bottom: 1px solid #eee;
  vertical-align: top;
}

pre {
  margin: 0;
  white-space: pre-wrap;
  font-size: 0.85rem;
}

.filters a {
  margin-right: 0.75rem;
  text-decoration: none;
  color: #555;
}

.filters a.active {
  font-weight: 700;
  color: var(--brand-ink);
  border-bottom: 2px solid var(--brand-gold);
}

.error {
  color: #dc2626;
}
/* Dashboard cards */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}

.card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 1.5rem 1rem;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  background: #fff;
  text-decoration: none;
  color: #222;
  cursor: pointer;
  font-family: inherit;
  font-size: 1rem;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
  /* Grid/flex items default to min-width:auto (their content's intrinsic
     width), which lets a long unbroken title (e.g. Brand Studio's logo
     names) force the card wider than its grid track instead of wrapping -
     this lets it shrink back down so overflow-wrap on .card-title below
     can actually do its job. Not pairing this with width:100% - .card uses
     the default content-box sizing (no global border-box reset in this
     stylesheet), so a content-box width:100% would add padding/border on
     top of the full track width and overflow into the next column.
     min-width:0 alone is enough; the grid's default stretch already sizes
     the card to its track. */
  min-width: 0;
}

.card:hover {
  /* Explicit here (not just inherited from the base .card rule) because
     some cards are <button> elements (e.g. /tvs's office/screen/add-slide
     cards) - the plain `button:hover` rule above is more specific than
     .card's own un-hovered background, and would otherwise win and turn
     the card dark on hover, making its text unreadable. */
  background: #fff;
  color: #222;
  transform: translateY(-2px);
  box-shadow: 0 4px 10px rgba(0,0,0,0.08);
}

.card-icon {
  font-size: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--brand-ink-soft);
}

.card-title {
  font-weight: 600;
  overflow-wrap: break-word;
  text-align: center;
  max-width: 100%;
}

.card-count {
  font-size: 0.85rem;
  color: #666;
}

.card-add {
  border: 2px dashed #cbd5e1;
  background: transparent;
  color: #64748b;
}

.template-card {
  position: relative;
}

.template-card .template-delete-btn {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
}

.card-add:hover {
  background: transparent;
  border-color: var(--brand-gold);
  color: var(--brand-hover);
}

/* Modal */
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(0,0,0,0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.modal.hidden {
  display: none;
}

.modal-content {
  background: #fff;
  border-radius: 10px;
  padding: 1.5rem;
  width: 100%;
  max-width: 420px;
  max-height: 85vh;
  overflow-y: auto;
}

.modal-content-wide {
  max-width: 720px;
}

.modal-content-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.modal-content-header h2 {
  margin: 0;
}

.modal-content-header a {
  font-size: 0.85rem;
  color: var(--brand-grey);
  text-decoration: none;
  white-space: nowrap;
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1.25rem;
}

.form-grid > label,
.form-grid > .checkbox-label,
.form-grid > fieldset {
  margin-bottom: 0.75rem;
}

.form-grid > .span-2 {
  grid-column: 1 / -1;
}

.form-hint {
  margin: -0.5rem 0 0.75rem;
  font-size: 0.85rem;
  color: var(--brand-grey);
}

.combobox {
  position: relative;
  min-width: 220px;
}

.combobox input[type="text"] {
  width: 100%;
}

.combobox-options {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  max-height: 240px;
  overflow-y: auto;
  background: white;
  border: 1px solid var(--brand-grey-light);
  border-radius: 6px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
  margin-top: 2px;
}

.combobox-options.hidden {
  display: none;
}

.combobox-option {
  padding: 0.4rem 0.75rem;
  cursor: pointer;
  font-size: 0.9rem;
}

.combobox-option:hover {
  background: var(--brand-hover-bg);
}

.combobox-option-empty {
  padding: 0.4rem 0.75rem;
  font-size: 0.9rem;
  color: var(--brand-grey);
}

.page-banner {
  background: var(--brand-hover-bg);
  border: 1px solid var(--brand-gold);
  border-radius: 6px;
  padding: 0.6rem 1rem;
  margin-bottom: 1rem;
}

.page-banner a {
  font-weight: 600;
}

@media (max-width: 640px) {
  .form-grid {
    grid-template-columns: 1fr;
  }
}

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

.modal-content h3 {
  margin-bottom: 0.5rem;
  font-size: 0.95rem;
}

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

.field-row .field-label {
  flex: 1;
  margin: 0;
}

.field-row .field-type {
  width: auto;
  margin: 0;
}

#add-field-btn {
  background: #f3f4f6;
  color: #333;
  margin-bottom: 1rem;
}

.modal-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
}

.modal-actions #cancel-category-btn {
  background: #f3f4f6;
  color: #333;
}
/* People: headshots */
.headshot-thumb {
  width: 100px;
  height: 100px;
  object-fit: cover;
  border-radius: 8px;
  margin-top: 0.5rem;
  display: block;
}

.headshot-thumb-sm {
  width: 36px;
  height: 36px;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

.headshot-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}

/* Per-person headshot crop tool - a single freeform selection box over the
   full-resolution photo, stored as [left,top,right,bottom] fractions
   (0-1) of the photo's own dimensions so it's independent of display size.
   Deliberately simpler than the graphics template editor's overlay system
   (one box, no anchors/z-order) since this only ever crops one photo. */
.crop-wrap {
  position: relative;
  display: inline-block;
  max-width: 100%;
  user-select: none;
  touch-action: none;
}

.crop-wrap img {
  display: block;
  max-width: 100%;
  max-height: 60vh;
  border-radius: 6px;
}

.crop-box {
  position: absolute;
  outline: 2px solid var(--brand-gold);
  background: rgba(255, 199, 44, 0.12);
  cursor: move;
  touch-action: none;
}

.crop-handle {
  position: absolute;
  width: 14px;
  height: 14px;
  background: var(--brand-gold);
  border: 1px solid var(--brand-ink);
  border-radius: 50%;
  touch-action: none;
}

.crop-handle[data-handle="nw"] { left: -7px; top: -7px; cursor: nwse-resize; }
.crop-handle[data-handle="ne"] { right: -7px; top: -7px; cursor: nesw-resize; }
.crop-handle[data-handle="sw"] { left: -7px; bottom: -7px; cursor: nesw-resize; }
.crop-handle[data-handle="se"] { right: -7px; bottom: -7px; cursor: nwse-resize; }

.headshot-placeholder {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-grey-light);
  color: var(--brand-grey);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.table-pagination {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.75rem;
}

.table-pagination button {
  padding: 0.35rem 0.9rem;
}

.table-pagination button:disabled {
  background: #9ca3af;
  cursor: default;
}

.table-pagination .pagination-info {
  color: #555;
  font-size: 0.9rem;
}

.tv-preview-img {
  max-width: 100%;
  max-height: 70vh;
  width: auto;
  height: auto;
  border-radius: 4px;
  margin-top: 1rem;
  display: block;
}

/* Drag-to-position editor overlay (top21_editor.html) */
.preview-wrap {
  position: relative;
  display: inline-block;
}

/* Static safe-margin guide - the brand-standard edge margin this app's
   graphics are built to (40px at native 1920x1080), always visible as a
   light reference so new positions stay consistent with it. */
.margin-guide {
  position: absolute;
  border: 1px dashed rgba(255, 255, 255, 0.3);
  pointer-events: none;
  z-index: 3;
}

/* Smart alignment guides - shown only while dragging, when the dragged
   element's edge/center lines up with the margin, canvas center, or
   another element. Bright pink is deliberate: it's a tool affordance, not
   part of the graphic, so it needs to read as "editor chrome" against any
   brand color the graphic itself uses. */
.snap-guide {
  position: absolute;
  background: #ff3ea5;
  pointer-events: none;
  z-index: 15;
  display: none;
  box-shadow: 0 0 4px rgba(255, 62, 165, 0.8);
}

.snap-guide.v {
  width: 1px;
  top: 0;
}

.snap-guide.h {
  height: 1px;
  left: 0;
}

.snap-guide.visible {
  display: block;
}

/* Chip label shown above the selected element ("Headline", "Grid", ...) */
.drag-handle-label {
  position: absolute;
  top: -24px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--brand-ink);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  white-space: nowrap;
  pointer-events: none;
  display: none;
}

/* Draggable text (headline/subtitle) rendered in the real brand font, right
   on top of the preview - click and drag the text itself, like a normal
   design tool, instead of a disconnected handle. Chrome (label, resize
   handle) only appears once selected - like Canva/Word, an unselected
   element is just plain content with a faint hover hint, not permanently
   covered in controls. */
.overlay-text {
  position: absolute;
  /* z-index is set inline by applyZIndexOrder() in templates_editor.html -
     it must follow each element's real stacking order (or the selected
     element), not a fixed per-type value here. */
  cursor: grab;
  user-select: none;
  touch-action: none;
  white-space: nowrap;
  padding: 2px 6px;
  margin: -2px -6px;
  border-radius: 4px;
  outline: 1px dashed transparent;
}

.overlay-text:hover {
  outline-color: rgba(255, 199, 44, 0.5);
}

.overlay-text.selected {
  outline: 2px solid var(--brand-gold);
}

.overlay-text:active {
  cursor: grabbing;
}

.overlay-grid-box {
  position: absolute;
  /* z-index is set inline by applyZIndexOrder() in templates_editor.html -
     see the .overlay-text comment above for why. */
  /* outline, not border - a border adds to the box's own measured size
     (content-box sizing), which would make the clickable/handle-anchoring
     box visibly bigger than the real element underneath it, especially
     noticeable for a thin rect like an underline bar. outline draws
     outside the box without changing its size, same trick .overlay-text
     already uses for its own selection ring. */
  outline: 1px dashed rgba(255, 199, 44, 0.35);
  outline-offset: -1px;
  cursor: grab;
  touch-action: none;
}

.overlay-grid-box:hover {
  outline-color: rgba(255, 199, 44, 0.7);
}

.overlay-grid-box.selected {
  outline: 2px solid var(--brand-gold);
  background: rgba(255, 199, 44, 0.08);
}

.overlay-grid-box:active {
  cursor: grabbing;
}

.overlay-text .overlay-resize-handle,
.overlay-grid-box .overlay-resize-handle,
.overlay-text .overlay-width-handle,
.overlay-text .drag-handle-label,
.overlay-grid-box .drag-handle-label,
.overlay-text .quick-toolbar {
  display: none;
}

.overlay-text.selected .overlay-resize-handle,
.overlay-grid-box.selected .overlay-resize-handle,
.overlay-text.selected .overlay-width-handle,
.overlay-text.selected .drag-handle-label,
.overlay-grid-box.selected .drag-handle-label {
  display: block;
}

.overlay-text.selected .quick-toolbar {
  display: flex;
}

/* Font + alignment, right on the element being edited - the common text
   controls, always one click away without opening the "Element settings"
   details panel. */
.quick-toolbar {
  position: absolute;
  top: -34px;
  left: 50%;
  transform: translateX(-50%);
  gap: 3px;
  background: var(--brand-ink);
  padding: 3px;
  border-radius: 5px;
  z-index: 14;
  white-space: nowrap;
  cursor: default;
}

.quick-toolbar select {
  font-size: 0.75rem;
  max-width: 130px;
  border-radius: 3px;
  border: none;
  padding: 2px 3px;
}

.quick-toolbar .qt-align {
  width: 22px;
  height: 22px;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  border-radius: 3px;
  border: none;
  background: #fff;
  color: var(--brand-ink);
  cursor: pointer;
  padding: 0;
}

.quick-toolbar .qt-align.active {
  background: var(--brand-gold);
}

.quick-toolbar {
  align-items: center;
}

.qt-color-swatch {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.45);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}

.qt-color-popover {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 4px;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  width: 96px;
  padding: 7px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35);
}

.qt-color-popover.hidden {
  display: none;
}

.qt-color-popover .sw {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px #ddd;
}

.qt-color-popover .sw:hover {
  box-shadow: 0 0 0 2px var(--brand-gold);
}

.qt-lh-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  color: #fff;
  font-size: 0.7rem;
}

.qt-lh-group button {
  width: 18px;
  height: 18px;
  border-radius: 3px;
  border: none;
  background: #fff;
  color: var(--brand-ink);
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.qt-lh-value {
  min-width: 26px;
  text-align: center;
}

.overlay-resize-handle {
  position: absolute;
  right: -4px;
  bottom: -4px;
  width: 7px;
  height: 7px;
  background: var(--brand-gold);
  border: 1px solid var(--brand-ink);
  border-radius: 50%;
  cursor: nwse-resize;
  touch-action: none;
  z-index: 12;
}

/* Side handle for a text element's box width - a pull/push on the edge,
   separate from the corner handle (which only ever changes font size).
   Positioned on whichever edge isn't anchored (JS sets left/right per
   element - see syncOverlays) since that's the edge that visually moves
   when width changes. Thin on purpose - it should read as an edge handle,
   not another box competing with the content for attention. */
.overlay-width-handle {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 4px;
  height: 15px;
  background: var(--brand-gold);
  border: 1px solid var(--brand-ink);
  border-radius: 2px;
  cursor: ew-resize;
  touch-action: none;
  z-index: 12;
}

/* Color dots - only shown (via JS display toggling, since they're not DOM
   descendants of the element they control) while that element is selected. */
.overlay-swatch {
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.45);
  cursor: pointer;
  z-index: 13;
  display: none;
}

.overlay-swatch-popover {
  position: absolute;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  width: 96px;
  padding: 7px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35);
}

.overlay-swatch-popover.hidden {
  display: none;
}

.overlay-swatch-popover .sw {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px #ddd;
}

.overlay-swatch-popover .sw:hover {
  box-shadow: 0 0 0 2px var(--brand-gold);
}

#config-form fieldset {
  margin-bottom: 1rem;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 0.75rem 1rem 1rem;
}

#config-form legend {
  font-weight: 600;
  padding: 0 0.4rem;
}

#config-form label {
  display: inline-block;
  width: 220px;
  margin: 0.3rem 0.5rem 0.3rem 0;
  vertical-align: top;
}

#config-form input,
#config-form select {
  width: 100%;
  margin-top: 0.2rem;
}

/* Generic freeform template editor (templates_editor.html) */
.editor-layout {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(260px, 300px);
  gap: 1.5rem;
  align-items: start;
}

/* Taller cap than the shared .tv-preview-img default (70vh) so a portrait
   (4x5) template isn't left looking small - height is the binding
   constraint for portrait images, so this alone fixes it without widening
   the whole page. margin-top:0 overrides the shared .tv-preview-img spacing
   rule - the overlay boxes are position:absolute against #tpl-preview
   starting at top:0, so any margin on the image itself shifts the real
   picture out from under them without moving the overlays to match. */
#tpl-preview .tv-preview-img {
  max-height: 82vh;
  margin-top: 0;
}

/* Collapsed-by-default side panels (Element/Template settings) - closed on
   load so the editor stays out of the way; the quick toolbar on the
   selected element covers font/align for everyday use. */
details.mini-details {
  margin-bottom: 0.75rem;
}

details.mini-details summary {
  cursor: pointer;
  font-weight: 600;
  padding: 0.6rem 0.85rem;
  background: #f3f4f6;
  border-radius: 8px;
  list-style: none;
}

details.mini-details summary::-webkit-details-marker {
  display: none;
}

details.mini-details summary::before {
  content: '+ ';
  color: var(--brand-ink);
}

details.mini-details[open] summary::before {
  content: '\2212 ';
}

details.mini-details[open] summary {
  border-radius: 8px 8px 0 0;
  margin-bottom: 0.75rem;
}

#element-form label,
#template-form label {
  display: block;
  margin: 0.5rem 0;
}

#element-form input,
#element-form select,
#element-form textarea,
#template-form input,
#template-form select {
  width: 100%;
  margin-top: 0.2rem;
}


/* Checkbox */
.checkbox-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.checkbox-label input[type="checkbox"] {
  width: auto;
  margin: 0;
}

/* Repeatable rows (licenses) */
.license-row {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  align-items: center;
}

.license-row input {
  margin: 0;
}

.remove-license-btn {
  flex-shrink: 0;
}

#add-license-btn {
  background: #f3f4f6;
  color: #333;
  margin-bottom: 1rem;
}

/* Property fieldsets */
fieldset {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  padding: 1rem;
  margin: 1rem 0;
}

fieldset legend {
  font-weight: 600;
  padding: 0 0.5rem;
  color: #444;
}

/* Template editor: grid cell-contents sub-panel */
.cell-parts-section {
  margin-top: 1rem;
  border-top: 1px solid #e5e7eb;
  padding-top: 0.75rem;
}

.cell-parts-section h4 {
  margin: 0 0 0.25rem;
}

.cell-parts-hint {
  color: var(--brand-grey);
  font-size: 0.85rem;
  margin: 0 0 0.5rem;
}

.cell-parts-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.75rem;
}

.cell-part-chip {
  background: #f3f4f6;
  color: #333;
  font-size: 0.8rem;
  font-weight: 500;
  padding: 0.3rem 0.6rem;
  border-radius: 999px;
  text-transform: none;
}

.cell-part-chip:hover {
  background: var(--brand-hover-bg);
  color: var(--brand-hover);
}

.cell-part-delete {
  font-size: 0.8rem;
  padding: 0.35rem 0.7rem;
  background: transparent;
  color: #dc2626;
  border: 1px solid #dc2626;
}

.cell-part-delete:hover {
  background: #fee2e2;
}

/* Grid cell-part overlays on the canvas - same visual language as
   .overlay-grid-box (dashed outline, gold when selected) but a distinct
   cyan tint so it reads as "one piece inside the selected grid", not
   another top-level element. Text parts keep their own content span fully
   transparent (the server already draws the real text for real - see the
   block comment above syncPartOverlays in templates_editor.html) except
   while actively being double-click-edited, when it needs to be visible
   enough to type into. */
.overlay-part-box {
  position: absolute;
  z-index: 2000;
  outline: 1px dashed rgba(34, 211, 238, 0.6);
  outline-offset: -1px;
  cursor: grab;
  touch-action: none;
}

.overlay-part-box:hover {
  outline-color: rgba(34, 211, 238, 0.9);
}

.overlay-part-box.selected {
  outline: 2px solid #22d3ee;
  background: rgba(34, 211, 238, 0.1);
}

.overlay-part-box:active {
  cursor: grabbing;
}

.overlay-part-box .drag-handle-label,
.overlay-part-box .overlay-resize-handle,
.overlay-part-box .quick-toolbar {
  display: none;
}

.overlay-part-box.selected .drag-handle-label,
.overlay-part-box.selected .overlay-resize-handle {
  display: block;
}

.overlay-part-text.selected .quick-toolbar {
  display: flex;
}

.overlay-part-text {
  white-space: nowrap;
  padding: 2px 4px;
  margin: -2px -4px;
}

.tpl-part-text-content {
  color: transparent;
  cursor: text;
}

.tpl-part-text-content[contenteditable="true"] {
  color: var(--brand-ink);
  background: #fff;
  outline: 2px solid var(--brand-gold);
  padding: 1px 3px;
}

/* Form actions / edit-cancel */
.form-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-top: 1rem;
}

.btn-cancel {
  /* Reset every button/element default explicitly (not just color) - this
     class is used on both <a> tags and <button> elements throughout the
     app, and a plain <button> would otherwise keep the generic dark
     background/padding/border-radius from the base `button` rule, making
     it look squished and too dark instead of a plain understated link. */
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: #666;
  text-decoration: none;
  cursor: pointer;
}

.btn-cancel:hover {
  /* background must be restated here (not just on the base rule above) -
     otherwise the generic `button:hover` rule's dark background wins on
     specificity for a <button>-based .btn-cancel, same issue .card:hover
     had to work around. */
  background: none;
  color: var(--brand-hover);
}

/* Status badges */
.status-badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
}

.status-active {
  background: #dcfce7;
  color: #166534;
}

.status-pending {
  background: #fef9c3;
  color: #854d0e;
}

/* Modifier on .status-badge: smaller pill for an inline "+N" count */
.license-extra-badge {
  padding: 0.05rem 0.45rem;
  font-size: 0.75rem;
  background: var(--brand-grey-light);
  color: var(--brand-ink-soft);
}

.status-closed {
  background: #e5e7eb;
  color: #374151;
}

.status-cancelled {
  background: #fee2e2;
  color: #991b1b;
}

.status-withdrawn {
  background: #ede9fe;
  color: #5b21b6;
}

.status-missing {
  background: #fef3c7;
  color: #92400e;
}

.status-expired {
  background: #fef3c7;
  color: #92400e;
}

/* Copy-to-clipboard icon button (e.g. next to an address) */
.copy-btn {
  display: inline-flex;
  align-items: center;
  background: transparent;
  color: #888;
  padding: 0 0.25rem;
  vertical-align: middle;
}

.copy-btn:hover {
  color: var(--brand-hover);
}

.copy-btn.copied {
  color: #16a34a;
}
/* Collapsible add-entry sections */
.add-entry summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 1.1rem;
  padding: 0.75rem 1rem;
  background: #f3f4f6;
  border-radius: 8px;
  list-style: none;
}

.add-entry summary::-webkit-details-marker {
  display: none;
}

.add-entry summary::before {
  content: '+ ';
  color: var(--brand-ink);
}

.add-entry[open] summary::before {
  content: '\2212 ';
}

.add-entry[open] summary {
  border-radius: 8px 8px 0 0;
  margin-bottom: 1rem;
}

/* Table search + sort */
.table-toolbar {
  margin-top: 1.5rem;
}

.table-toolbar input[type="search"] {
  width: 100%;
  max-width: 320px;
  padding: 0.5rem;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  box-sizing: border-box;
}

.table-toolbar + table {
  margin-top: 0.75rem;
}

th.sortable-col {
  cursor: pointer;
  user-select: none;
}

th.sortable-col:hover {
  color: var(--brand-hover);
}

th.sort-asc::after {
  content: ' \25B2';
}

th.sort-desc::after {
  content: ' \25BC';
}

/* Data tables (Property, People) - compact and dense on purpose, with a
   row hover so a row is easy to track across a lot of columns. Property's
   address also splits into two left-justified lines (street on top,
   city/state/zip below) instead of one long line, so it never needs a
   wide column or truncation, and agent names stack one per line at a
   smaller size than the rest of the table. Every row stays a single,
   predictable height. */
#property-table,
#people-table {
  font-size: 0.9rem;
}

/* Fixed layout + the <colgroup> in property.html give every column a
   deliberate width, so one row with an unusually long buyer's agent name
   can't steal space from the Address column (which was squeezing Address
   and leaving a lot of dead space in Buyer's Agent for every other row). */
#property-table {
  table-layout: fixed;
}

#property-table th,
#property-table td,
#people-table th,
#people-table td {
  padding: 0.4rem 0.5rem;
}

#property-table td,
#people-table td {
  vertical-align: middle;
}

#property-table tbody tr:hover,
#people-table tbody tr:hover {
  background: var(--brand-hover-bg);
}

/* Nothing in a data row should wrap to a second line by default - a
   wrapped cell makes that one row taller than every other row. The
   address/agent cells still stack multiple *lines* (see below), but that's
   separate block-level divs, not text wrapping, so this doesn't fight it.
   The status-history dropdown is the one place normal wrapping is wanted. */
#property-table td,
#people-table td {
  white-space: nowrap;
}

.history-panel {
  white-space: normal;
}

/* Office name shown smaller than the rest of the row - it's context, not
   the primary thing being scanned for (the address / person's name is). */
.cell-office {
  font-size: 0.82rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cell-address {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
}

.address-lines {
  min-width: 0;
  flex: 1;
}

.address-street,
.address-citystate {
  overflow: hidden;
  text-overflow: ellipsis;
}

.address-citystate {
  font-size: 0.8rem;
  color: var(--brand-grey);
}

.cell-address .copy-btn {
  margin-left: auto;
  flex-shrink: 0;
}

.agent-lines {
  font-size: 0.82rem;
  line-height: 1.35;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

#team-member-list {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--brand-grey-light);
  border-radius: 6px;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.75rem;
}

.agent-line {
  overflow: hidden;
  text-overflow: ellipsis;
}

.agent-team {
  font-size: 0.72rem;
  color: var(--brand-grey);
  overflow: hidden;
  text-overflow: ellipsis;
}

.cell-muted {
  color: var(--brand-grey);
}

/* Read-only property detail modal */
.property-detail-body {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.detail-row {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}

.detail-row-stacked {
  flex-direction: column;
  gap: 0.3rem;
}

.detail-label {
  flex: 0 0 140px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--brand-grey);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.detail-value {
  color: var(--brand-ink);
}

.detail-team {
  color: var(--brand-grey);
  font-size: 0.85em;
}

.detail-description {
  margin: 0;
  white-space: pre-wrap;
}

.detail-photo {
  width: 220px;
  height: 220px;
}

/* Table row actions (Edit / Delete / History) */
.row-actions {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: nowrap;
  white-space: nowrap;
}

.history-panel {
  margin-top: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  font-size: 0.85rem;
}

.history-panel ul {
  margin: 0;
  padding-left: 1.1rem;
}

/* Reports page status messages */
#report-status.success {
  color: #166534;
  font-weight: 600;
}

#report-status.error {
  color: #dc2626;
  font-weight: 600;
}

/* Marketing planner: to-do list + content calendar */
.marketing-layout {
  display: flex;
  gap: 2rem;
  margin-top: 1.5rem;
  align-items: flex-start;
}

.todo-panel {
  flex: 0 0 340px;
}

.calendar-panel {
  flex: 1;
  min-width: 0;
}

.todo-panel h3 {
  font-size: 1rem;
  margin: 1.25rem 0 0.5rem;
  color: var(--brand-grey);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.todo-empty {
  color: var(--brand-grey);
  font-size: 0.9rem;
  margin: 0.25rem 0 0;
}

.todo-group {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.task-row {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.5rem 0.6rem;
  border: 1px solid #e5e7eb;
  border-left: 4px solid var(--brand-grey);
  border-radius: 8px;
  background: #fff;
}

.task-row.task-done {
  opacity: 0.55;
}

.task-row.task-done .task-title {
  text-decoration: line-through;
}

.task-row-main {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.task-row-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.3rem 0.6rem;
  padding-left: 1.5rem;
}

.task-check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1 1 160px;
  min-width: 160px;
  margin: 0;
  cursor: pointer;
}

.task-check input[type="checkbox"] {
  width: auto;
  margin: 0;
  flex-shrink: 0;
}

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

.task-category-badge {
  flex-shrink: 0;
  font-size: 0.75rem;
  font-weight: 700;
  white-space: nowrap;
}

.task-due {
  flex-shrink: 0;
  font-size: 0.8rem;
  color: var(--brand-grey);
}

.task-row-buttons {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex-shrink: 0;
  margin-left: auto;
}

.task-due-overdue {
  color: #dc2626;
  font-weight: 700;
}

.task-recurrence-label {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: 0.8rem;
  color: var(--brand-grey);
}

.task-scheduled-badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: 0.75rem;
  font-weight: 700;
  color: #2F7D6E;
}

.todo-done-section {
  margin-top: 1.25rem;
}

.todo-done-section summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--brand-grey);
}

.todo-done-section .todo-group {
  margin-top: 0.5rem;
}

.calendar-header {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
}

.calendar-header h2 {
  margin: 0;
  min-width: 220px;
  text-align: center;
}

.cal-nav {
  text-decoration: none;
}

.cal-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem 1rem;
  margin: 0.5rem 0 1rem;
}

.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: var(--brand-ink-soft);
}

.legend-toggle {
  background: none;
  border: none;
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
  cursor: pointer;
  font-family: inherit;
}

.legend-toggle:hover {
  background: var(--brand-grey-light);
}

.legend-toggle.legend-off {
  color: var(--brand-grey);
  text-decoration: line-through;
  opacity: 0.6;
}

.legend-toggle.legend-off .legend-dot {
  background: transparent !important;
  box-shadow: inset 0 0 0 2px var(--brand-grey);
}

.legend-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}

.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  align-items: center;
  margin-bottom: 0.75rem;
}

.checkbox-group-label {
  flex-basis: 100%;
  font-size: 0.85rem;
  color: var(--brand-grey);
  margin-bottom: 0.15rem;
}

.checkbox-group .checkbox-label {
  display: inline-flex;
}

.buffer-not-connected {
  font-size: 0.7rem;
  color: var(--brand-grey);
  margin-left: 0.25rem;
}

.graphic-thumb {
  max-width: 160px;
  max-height: 160px;
  object-fit: cover;
  border-radius: 8px;
  display: block;
}

#ltt-graphic-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

#buffer-schedule-field {
  margin-bottom: 0.75rem;
}

#buffer-schedule-results {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
}

.buffer-result-scheduled {
  color: #2F7D6E;
}

.buffer-result-error {
  color: #dc2626;
}

.buffer-result-not_connected {
  color: var(--brand-grey);
}

/* Ready to Schedule queue */
/* Capped (not 1fr) so a handful of pending graphics don't stretch to fill
   the row - same fix as .brand-asset-grid below for the same 1fr-with-few-
   items bug. */
.rts-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 300px));
  gap: 1.25rem;
  margin-top: 1.5rem;
}

.rts-card {
  display: flex;
  flex-direction: column;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  overflow: hidden;
}

.rts-thumb-wrap {
  position: relative;
}

.rts-thumb {
  width: 100%;
  height: 150px;
  object-fit: cover;
  display: block;
  background: var(--brand-grey-light);
}

.rts-image-count-badge {
  position: absolute;
  bottom: 0.5rem;
  right: 0.5rem;
  background: rgba(18, 18, 18, 0.72);
  color: #fff;
}

/* A batched card's photo strip - drag thumbnails to reorder, × to remove a
   single photo without dismissing the whole post. */
.rts-gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0.6rem;
  background: var(--brand-grey-light);
}

.rts-gallery-item {
  position: relative;
  width: 64px;
  height: 64px;
  cursor: grab;
}

.rts-gallery-item.dragging {
  opacity: 0.4;
}

.rts-gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 6px;
  display: block;
  pointer-events: none;
}

.rts-gallery-remove-btn {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 20px;
  height: 20px;
  line-height: 18px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(18, 18, 18, 0.8);
  color: #fff;
  font-size: 0.85rem;
  cursor: pointer;
}

.rts-gallery-remove-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.rts-card-body {
  padding: 1rem;
  min-width: 0;
}

.rts-card-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.rts-heading-left {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  min-width: 0;
}

.rts-select-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  flex-shrink: 0;
  font-size: 0.65rem;
  color: var(--brand-grey);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.rts-combine-bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--brand-hover-bg);
  border: 1px solid var(--brand-gold);
  border-radius: 8px;
  padding: 0.6rem 1rem;
  margin-top: 1.5rem;
}

.rts-card-title {
  margin: 0;
  font-size: 1rem;
  overflow-wrap: break-word;
}

.rts-type-badge {
  background: var(--brand-hover-bg);
  color: var(--brand-hover);
  flex-shrink: 0;
}

/* Groups a card's form into visually distinct sections (caption vs.
   platforms/date) instead of one long unbroken stack of fields. */
.rts-section {
  padding-bottom: 0.9rem;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid #f0f0f0;
}

.rts-section:last-of-type {
  border-bottom: none;
  margin-bottom: 0;
  padding-bottom: 0;
}

.rts-hashtag-preview {
  margin: -0.5rem 0 0;
  overflow-wrap: break-word;
}

.rts-results {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
}

/* form textarea (global) defaults to a monospace font meant for the app's
   structured data-entry forms (Property, People) - overridden here since a
   social caption/hashtag list should read like normal prose. Also softens
   the plain-square browser default border/corners on this page's inputs to
   match the rounded, low-contrast feel of the cards/badges around them. */
.rts-card-body textarea,
.rts-panel textarea {
  font-family: inherit;
}

.rts-card-body input,
.rts-card-body textarea,
.rts-card-body select,
.rts-panel input,
.rts-panel textarea,
.rts-panel select {
  border: 1px solid var(--brand-grey-light);
  border-radius: 6px;
}

.rts-panel {
  background: #fafafa;
  border: 1px solid #e5e7eb;
  border-radius: 0 0 8px 8px;
  padding: 1rem;
}

.rts-hashtag-row {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 0.75rem;
  margin-bottom: 0.75rem;
}

.rts-hashtag-row-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}

.rts-hashtag-row-header input {
  margin-top: 0;
}

.rts-hashtag-label {
  font-weight: 600;
}

.rts-hashtag-label-input {
  flex: 1;
  font-weight: 600;
}

#rts-add-type-btn {
  margin-bottom: 0.75rem;
}

#hashtags-status.success {
  color: #166534;
}

/* Celebrations - multiple grid pages when a month's headcount overflows one
   slide/post (see app.py's _generate_celebration_pages) */
.cel-page + .cel-page {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid #e5e7eb;
}

.ltt-or {
  text-align: center;
  color: var(--brand-grey);
  font-size: 0.85rem;
  margin: 0.75rem 0;
}

#ltt-existing-select {
  width: 100%;
  margin-bottom: 0.5rem;
}

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

.calendar-dow {
  text-align: center;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--brand-grey);
  text-transform: uppercase;
  padding-bottom: 0.25rem;
}

.calendar-day {
  height: 96px;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 0.35rem;
  background: #fff;
  overflow-y: auto;
}

.calendar-day.outside {
  background: #fafafa;
  color: #bbb;
}

.calendar-day.today {
  border: 2px solid var(--brand-gold);
}

.calendar-day-num {
  font-size: 0.8rem;
  font-weight: 700;
  margin-bottom: 0.25rem;
}

.cal-pill {
  font-size: 0.7rem;
  background: var(--brand-grey-light);
  color: var(--brand-ink-soft);
  border-left: 3px solid var(--brand-grey);
  border-radius: 3px;
  padding: 0.1rem 0.3rem;
  margin-bottom: 0.2rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cal-pill[data-id] {
  cursor: pointer;
}

.cal-pill[data-id]:hover {
  filter: brightness(0.95);
}

.cal-pill-done {
  opacity: 0.5;
  text-decoration: line-through;
}

.cal-pill-overdue {
  background: #fee2e2;
  color: #991b1b;
}

.cal-pill-scheduled {
  border-left-width: 4px;
}

.cal-pill-check {
  vertical-align: -1px;
  margin-right: 2px;
  color: #2F7D6E;
}

.cal-pill-hidden {
  display: none;
}

.cal-pill-external {
  font-style: italic;
  cursor: pointer;
}

.cal-pill-external:hover {
  filter: brightness(0.95);
}

.cal-popover {
  position: absolute;
  z-index: 50;
  width: 260px;
  background: #fff;
  border-radius: 8px;
  border-left: 4px solid var(--brand-grey);
  box-shadow: 0 4px 18px rgba(0,0,0,0.18);
  padding: 0.85rem 1rem;
}

.cal-popover.hidden {
  display: none;
}

.cal-popover-close {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  line-height: 1;
  color: var(--brand-grey);
}

.cal-popover-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.cal-popover-title {
  font-weight: 700;
  color: var(--brand-ink);
  margin: 0.3rem 0 0.4rem;
}

.cal-popover-date,
.cal-popover-time {
  font-size: 0.85rem;
  color: var(--brand-ink-soft);
}

.cal-popover-title-done {
  text-decoration: line-through;
  color: var(--brand-grey);
}

.cal-popover-time.hidden {
  display: none;
}

.cal-popover-scheduled {
  font-size: 0.75rem;
  font-weight: 700;
  color: #2F7D6E;
  margin-top: 0.2rem;
}

.cal-popover-scheduled.hidden {
  display: none;
}

.cal-popover-notes {
  font-size: 0.85rem;
  color: var(--brand-ink-soft);
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--brand-grey-light);
  white-space: pre-wrap;
}

.cal-popover-notes.hidden {
  display: none;
}

.cal-popover-edit {
  margin-top: 0.75rem;
  font-size: 0.8rem;
  padding: 0.35rem 0.8rem;
}

.cal-popover-edit.hidden {
  display: none;
}

@media (max-width: 800px) {
  .marketing-layout {
    flex-direction: column;
  }

  .todo-panel {
    flex-basis: auto;
    width: 100%;
  }
}

/* Dashboard: This Week + To-Do widgets */
.dash-planner {
  display: flex;
  gap: 2rem;
  margin: 1.5rem 0 2rem;
  align-items: flex-start;
}

.dash-week {
  flex: 1;
  min-width: 0;
}

.dash-todo {
  flex: 0 0 320px;
}

.dash-panel-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}

.dash-panel-header h2 {
  margin: 0;
}

.dash-panel-header a {
  font-size: 0.85rem;
  color: var(--brand-grey);
  text-decoration: none;
  white-space: nowrap;
}

.dash-panel-header a:hover {
  color: var(--brand-hover);
}

.week-strip {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin-top: 0.75rem;
}

.week-day {
  height: 110px;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 0.4rem;
  background: #fff;
  overflow-y: auto;
}

.week-day.today {
  border: 2px solid var(--brand-gold);
}

.week-day-label {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--brand-grey);
  text-transform: uppercase;
  margin-bottom: 0.3rem;
}

.week-day-empty {
  color: #ccc;
  font-size: 0.8rem;
}

.dash-todo .todo-group {
  margin-top: 0.75rem;
}

@media (max-width: 900px) {
  .dash-planner {
    flex-direction: column;
  }

  .dash-todo {
    flex-basis: auto;
    width: 100%;
  }

  .week-strip {
    grid-template-columns: repeat(7, minmax(80px, 1fr));
    overflow-x: auto;
  }
}

/* Saved (custom) reports */
.report-row {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.5rem 0.6rem;
  border: 1px solid #e5e7eb;
  border-left: 4px solid var(--brand-grey);
  border-radius: 8px;
  background: #fff;
  margin-bottom: 0.5rem;
}

.report-row-main {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.report-row-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.report-row-meta {
  padding-left: 0;
  font-size: 0.75rem;
  color: var(--brand-grey);
}

.report-run {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8rem;
  padding: 0.3rem 0.6rem;
}

#report-results {
  margin-top: 1.5rem;
}

/* Page header with an inline "+" action (Marketing planner) */
.page-header {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.page-header h1 {
  margin: 0;
}

/* Icon buttons in a page header (e.g. property page's "refresh" check) sit
   at the same size/weight as row-action icon buttons, just not inside a
   table row. */
.page-header .icon-btn {
  width: 2.1rem;
  height: 2.1rem;
}

.page-header .icon-btn.spinning .hi {
  animation: icon-spin 0.8s linear infinite;
}

@keyframes icon-spin {
  to { transform: rotate(360deg); }
}

#daily-check-status {
  margin: -0.5rem 0 0.5rem;
  font-size: 0.85rem;
  color: var(--brand-grey);
}

#daily-check-status.success {
  color: #166534;
}

#daily-check-status.error {
  color: #dc2626;
}

.fab-add {
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  font-size: 1.3rem;
  line-height: 1;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.add-person-wrap {
  position: relative;
  display: inline-block;
}

.dropdown-menu {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 50;
  min-width: 190px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 18px rgba(0,0,0,0.18);
  padding: 0.35rem;
}

.dropdown-menu.hidden {
  display: none;
}

.dropdown-menu-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.65rem;
  border-radius: 6px;
  font-size: 0.9rem;
  font-family: inherit;
  color: var(--brand-ink);
  text-decoration: none;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
}

.dropdown-menu-item:hover {
  color: var(--brand-hover);
  background: var(--brand-hover-bg);
}

.month-filter-card {
  margin-top: 1rem;
  padding: 0.9rem 1.1rem;
  background: var(--brand-grey-light);
  border-radius: 8px;
}

.month-filter-form {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.month-filter-label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0;
  font-weight: 600;
  color: var(--brand-ink);
}

.month-filter-form select {
  width: auto;
  margin-top: 0;
}

.month-filter-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  background: #fff;
  color: var(--brand-ink-soft);
  font-size: 0.85rem;
  font-weight: 600;
}

.month-filter-clear {
  display: inline-flex;
  color: var(--brand-grey);
}

.month-filter-clear:hover {
  color: var(--brand-hover);
}

/* --------------------------------------------------------------------- */
/* Auth: nav user area, login page                                       */
/* --------------------------------------------------------------------- */

nav .nav-spacer {
  margin-left: auto;
}

.nav-user {
  display: flex;
  align-items: center;
  gap: 1rem;
  font-weight: 600;
}

.nav-user-name {
  color: var(--brand-grey);
  font-weight: 500;
  font-size: 0.9rem;
}

.nav-logout-btn {
  background: none;
  border: none;
  color: var(--brand-ink);
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
}

.nav-logout-btn:hover {
  color: var(--brand-hover);
  background: none;
}

.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-grey-light);
}

.login-card {
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  padding: 2.5rem 3rem;
  text-align: center;
  max-width: 360px;
}

.login-logo {
  height: 32px;
  margin-bottom: 1.5rem;
}

.login-card h1 {
  margin: 0 0 1.5rem;
}

.google-signin-btn {
  display: inline-block;
  background: var(--brand-ink);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  padding: 0.75rem 1.5rem;
  border-radius: 6px;
}

/* Open Houses page */
#import-status.success,
#sync-photos-status.success,
#generate-all-status.success {
  color: #166534;
  font-weight: 600;
}

#import-status.error,
#sync-photos-status.error,
#generate-all-status.error {
  color: #dc2626;
  font-weight: 600;
}

.oh-day {
  color: var(--brand-grey);
  font-size: 0.8rem;
}

.hosting-agent-input {
  max-width: 220px;
  width: 100%;
  box-sizing: border-box;
  padding: 0.4rem;
  font-family: inherit;
}

.oh-photo-cell {
  min-width: 90px;
}

.oh-photo-thumb {
  display: block;
  width: 80px;
  height: 56px;
  object-fit: cover;
  border-radius: 4px;
  margin-bottom: 0.25rem;
}

.oh-photo-none {
  display: block;
  color: var(--brand-grey);
  font-size: 0.85rem;
  margin-bottom: 0.25rem;
}

.oh-photo-source {
  display: block;
  color: var(--brand-grey);
  font-size: 0.75rem;
  margin-bottom: 0.25rem;
}

.oh-photo-upload-label {
  color: var(--brand-hover);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
}

.google-signin-btn:hover {
  background: var(--brand-ink-soft);
}

/* Only rendered when Flask is running with FLASK_DEBUG=1 (see base.html) -
   a visual tell so a local dev instance never gets mistaken for the
   office's shared production instance. */
/* Slide preview popover (Manage TV playlists on /tvs) - same floating-card
   language as .cal-popover, just wider to fit a thumbnail image instead of
   text. Positioned near the clicked Preview button by JS, closed via the
   shared .cal-popover-close styling. */
.slide-preview-popover {
  position: absolute;
  z-index: 50;
  width: 340px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 18px rgba(0,0,0,0.18);
  padding: 0.85rem 1rem;
}

.slide-preview-popover.hidden {
  display: none;
}

.slide-preview-popover-title {
  font-weight: 700;
  color: var(--brand-ink);
  margin: 0 1.5rem 0.6rem 0;
}

.slide-preview-popover img {
  display: block;
  width: 100%;
  border-radius: 4px;
}

/* Generic show/hide utility - most other toggled elements in this app scope
   their own `.x.hidden` rule, but the TV playlist manager (/tvs) has several
   independent plain divs (screen-cards, playlist-view, add-slide-form) that
   don't need their own component-specific rule just for this. */
.hidden {
  display: none;
}

/* TV playlist manager (/tvs): office -> screen -> playlist drill-down */
#office-cards,
#screen-cards,
#playlist-view {
  margin-top: 1rem;
}

.slide-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 1rem;
}

.slide-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  background: #fff;
}

.slide-row.dragging {
  opacity: 0.4;
}

.slide-drag-handle {
  cursor: grab;
  color: var(--brand-grey);
  font-size: 1.1rem;
  line-height: 1;
  width: 1rem;
  flex-shrink: 0;
  text-align: center;
}

.slide-name-wrap {
  flex: 1;
  min-width: 0;
}

.slide-name {
  cursor: pointer;
  border-bottom: 1px dashed transparent;
}

.slide-name:hover {
  border-bottom-color: var(--brand-grey);
}

.slide-name-input {
  width: 100%;
  max-width: 320px;
}

.slide-duration {
  flex-shrink: 0;
  color: var(--brand-grey);
  font-size: 0.85rem;
  width: 3rem;
}

.slide-actions {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex-shrink: 0;
}

.slide-list .card-add {
  flex-direction: row;
  justify-content: center;
  padding: 0.75rem;
}

.slide-list .card-add .card-icon {
  font-size: 1rem;
}

.dev-server-badge {
  position: fixed;
  bottom: 12px;
  right: 12px;
  z-index: 9999;
  background: #dc2626;
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}

/* Brand Studio (/admin/brand-studio) */

/* Category headers interleaved into the *same* .card-grid as the logo
   cards (rather than a separate grid per category) - a separate grid per
   category meant each one's 1fr columns divided that category's own item
   count, so a category with only 1-2 logos got huge stretched cards while
   a category with a dozen got small ones. One continuous grid means every
   card divides the same row width the same way, so they're all uniform. */
.card-grid-header {
  grid-column: 1 / -1;
  margin: 1.25rem 0 0;
}

.card-grid-header:first-child {
  margin-top: 0;
}

/* .card's default 180px/1.5rem padding is sized for a handful of large
   dashboard nav tiles - way too roomy for a dense library of dozens of
   small asset thumbnails, which is what made these look oversized. Its own
   grid sizing + a tighter .brand-asset-card override below instead. */
.brand-asset-grid {
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 0.6rem;
}

.brand-asset-card {
  position: relative;
  padding: 0.5rem;
  gap: 0.3rem;
  /* Fixed height (not just centered content) so a 1-line title and a
     2-line wrapped title still produce identically-sized cards - grid rows
     already stretch every card in the *same* row to match, but two
     different rows are otherwise free to differ. */
  height: 110px;
}

.brand-asset-thumb {
  width: 100%;
  height: 55px;
  object-fit: contain;
  background: var(--brand-grey-light);
  border-radius: 4px;
}

.brand-asset-card .card-title {
  font-size: 0.75rem;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.brand-asset-card .brand-delete-btn {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
}

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

.brand-document-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  margin-bottom: 0.4rem;
}

.brand-document-list li a {
  /* Same flex-item min-width:auto fix as .card above - lets a long
     document name wrap/truncate instead of pushing past the row's edge. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#notes-save-status.success {
  color: #166534;
}