{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "marker",
  "title": "Marker",
  "description": "A quiet line in a conversation: a status, where a day begins, where you left off, or how long it went quiet.",
  "registryDependencies": [
    "https://thedirectors.agency/ui/r/0nlytype.json"
  ],
  "files": [
    {
      "path": "registry/0nlytype/ui/marker.tsx",
      "content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype MarkerProps = React.ComponentProps<\"p\"> & {\n  /**\n   * status (the default): a quiet line. divider: where a day begins, the word standing on the rule it\n   * pushed apart. ribbon: where you left off, the one accent line across the page. lapse: a pause in\n   * the conversation, given as silence: the longer it was, the more room and the looser the words.\n   */\n  variant?: \"status\" | \"divider\" | \"ribbon\" | \"lapse\"\n  /** A small dot before a status. */\n  dot?: boolean\n  /** Lapse only: how long the pause was, in minutes. A minute is a breath; a week is the widest. */\n  minutes?: number\n  /** Plays the arrival when it mounts. */\n  arriving?: boolean\n  /** Divider only. vertical stands it up between two things in a row, as tall as the row; a word reads down it. */\n  orientation?: \"horizontal\" | \"vertical\"\n}\n\n// ponytail: log scale, clamped at a week; a longer silence looks like a week's.\nconst WEEK = 7 * 24 * 60\nconst lapseOf = (minutes = 0) => Math.min(1, Math.log1p(Math.max(0, minutes)) / Math.log1p(WEEK))\n\n/** A quiet line in a conversation: a status, where a day begins, where you left off, or a pause. A divider with no word is a plain rule. */\nfunction Marker({ variant = \"status\", dot, minutes, arriving, orientation = \"horizontal\", className, style, children, ...props }: MarkerProps) {\n  const upright = variant === \"divider\" && orientation === \"vertical\"\n  // A divider with no word is a rule and nothing else: say so, and which way it stands.\n  const bare = variant === \"divider\" && (children == null || children === false || children === \"\")\n  return (\n    <p\n      data-slot=\"marker\"\n      data-variant={variant === \"status\" ? undefined : variant}\n      data-orientation={upright ? \"vertical\" : undefined}\n      data-arriving={arriving || undefined}\n      role={bare ? \"separator\" : undefined}\n      aria-orientation={bare && upright ? \"vertical\" : undefined}\n      className={cn(\"ot-marker\", className)}\n      style={variant === \"lapse\" ? ({ \"--lapse\": lapseOf(minutes).toFixed(3), ...style } as React.CSSProperties) : style}\n      {...props}\n    >\n      {dot ? <span className=\"ot-marker-dot\" aria-hidden=\"true\" /> : null}\n      {children}\n    </p>\n  )\n}\n\nexport { Marker, type MarkerProps }\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/0nlytype/styles/marker.css",
      "content": "@layer components {\n  /* ── ot-marker ── a quiet line in a conversation: a status, a day, where you left off, or a pause */\n  .ot-marker { display: flex; align-items: center; gap: var(--ot-space-3); font-size: var(--ot-pp); line-height: var(--ot-pp-lh); color: var(--ot-pencil); }\n  .ot-marker-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }\n\n  /* divider: the word stands on the rule it pushed apart (\"Less is more.\" sets its rules on the baselines). */\n  .ot-marker[data-variant=\"divider\"] { align-items: baseline; gap: var(--ot-space-4); color: var(--ot-graphite); }\n  .ot-marker[data-variant=\"divider\"]::before, .ot-marker[data-variant=\"divider\"]::after { content: \"\"; flex: 1; block-size: var(--ot-hairline); background: var(--ot-rule-strong); }\n  .ot-marker[data-variant=\"divider\"]::before { transform-origin: 100% 50%; }\n  .ot-marker[data-variant=\"divider\"]::after { transform-origin: 0 50%; }\n  :is([dir=\"rtl\"], [dir=\"rtl\"] *).ot-marker[data-variant=\"divider\"]::before { transform-origin: 0 50%; }\n  :is([dir=\"rtl\"], [dir=\"rtl\"] *).ot-marker[data-variant=\"divider\"]::after { transform-origin: 100% 50%; }\n  .ot-marker[data-variant=\"divider\"][data-arriving]::before, .ot-marker[data-variant=\"divider\"][data-arriving]::after { animation: ot-draw-x var(--ot-andante) var(--ot-exhale) backwards; }\n  /* With no word the two rules meet: one unbroken hairline, which arriving still draws outward from its middle. */\n  .ot-marker[data-variant=\"divider\"]:empty { gap: 0; }\n  /* vertical: the rule stands up between two things in a row (\"Less is more.\" rules its columns), as tall as the row.\n     The marker turns on its side (writing-mode), so a word reads down it like a spine and the rules run above and below. */\n  .ot-marker[data-variant=\"divider\"][data-orientation=\"vertical\"] { writing-mode: vertical-rl; align-self: stretch; }\n  .ot-marker[data-variant=\"divider\"][data-orientation=\"vertical\"]::before { transform-origin: 50% 100%; }\n  .ot-marker[data-variant=\"divider\"][data-orientation=\"vertical\"]::after { transform-origin: 50% 0; }\n  .ot-marker[data-variant=\"divider\"][data-orientation=\"vertical\"][data-arriving]::before, .ot-marker[data-variant=\"divider\"][data-orientation=\"vertical\"][data-arriving]::after { animation-name: ot-draw-y; }\n\n  /* ribbon: the book's ribbon, laid across the page where you stopped reading. The one accent line. */\n  .ot-marker[data-variant=\"ribbon\"] { align-items: baseline; gap: var(--ot-space-3); color: var(--ot-accent); font-weight: 500; }\n  .ot-marker[data-variant=\"ribbon\"]::before { content: \"\"; flex: 1; height: var(--ot-stroke); background: currentColor; transform-origin: 0 50%; }\n  :is([dir=\"rtl\"], [dir=\"rtl\"] *).ot-marker[data-variant=\"ribbon\"]::before { transform-origin: 100% 50%; }\n  .ot-marker[data-variant=\"ribbon\"][data-arriving]::before { animation: ot-draw-x var(--ot-andante) var(--ot-exhale) backwards; }\n\n  /* lapse: no rule at all. The pause is the room around the words and the space between their letters. */\n  .ot-marker[data-variant=\"lapse\"] {\n    --lapse: 0;\n    justify-content: center; text-align: center;\n    padding-block: calc(var(--ot-space-3) + var(--lapse) * (var(--ot-space-8) - var(--ot-space-3)));\n    --lapse-tr: calc(var(--ot-pp-tr) + var(--lapse) * 0.36em);\n    letter-spacing: var(--lapse-tr); padding-inline-start: var(--lapse-tr); /* the tracking trails the last letter; this puts it back in the middle */\n    font-variant-numeric: tabular-nums;\n  }\n  /* Tracking breaks a joined script apart; there the pause widens the word spaces instead. */\n  .ot-marker[data-variant=\"lapse\"]:lang(ar, fa, ur) { letter-spacing: normal; padding-inline-start: 0; word-spacing: calc(var(--lapse) * 1.2em); }\n  .ot-marker[data-variant=\"lapse\"][data-arriving] { animation: ot-marker-open var(--ot-andante) var(--ot-exhale) backwards; }\n\n  .ot-marker[data-arriving] { animation: ot-arrive var(--ot-moderato) var(--ot-exhale) backwards; }\n  @keyframes ot-marker-open { from { padding-block: 0; padding-inline-start: 0; letter-spacing: var(--ot-pp-tr); opacity: 0; } }\n\n  @media (forced-colors: active) {\n    .ot-marker[data-variant=\"divider\"]::before, .ot-marker[data-variant=\"divider\"]::after { forced-color-adjust: none; background: CanvasText; }\n    .ot-marker[data-variant=\"ribbon\"] { color: Highlight; }\n    .ot-marker[data-variant=\"ribbon\"]::before { forced-color-adjust: none; background: Highlight; }\n  }\n}\n",
      "type": "registry:file",
      "target": "styles/0nlytype/marker.css"
    }
  ],
  "css": {
    "@import \"../styles/0nlytype/marker.css\"": {}
  },
  "meta": {
    "movement": "XI",
    "underneath": "native",
    "contract": "ot-marker"
  },
  "type": "registry:ui"
}
