{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://shayach.co.il/v1/config.schema.json",
  "title": "Shayach configuration (window.A11yConfig)",
  "description": "Every option is optional. Unknown keys and invalid values are ignored with a console warning prefixed [shayach].",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "language": {
      "enum": [
        "auto",
        "he",
        "ar",
        "ru",
        "en"
      ],
      "default": "auto",
      "description": "Default panel language. 'auto' uses the page's lang attribute when it is he, ar, ru or en, otherwise Hebrew. A visitor's own choice always wins."
    },
    "statementUrl": {
      "type": "string",
      "description": "http(s) or relative URL of the site's accessibility statement page. When set, the panel footer links to it."
    },
    "icon": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "position": {
          "enum": [
            "auto",
            "top-right",
            "top-left",
            "upper-right",
            "upper-left",
            "middle-right",
            "middle-left",
            "lower-right",
            "lower-left",
            "bottom-right",
            "bottom-left"
          ],
          "default": "auto",
          "description": "'auto' is bottom-right on RTL pages and bottom-left on LTR pages. upper and lower sit a quarter and three quarters of the way down the screen. A visitor who moves the button (see draggable) sees their own choice."
        },
        "offsetX": {
          "type": "number",
          "minimum": 0,
          "maximum": 200,
          "default": 20,
          "description": "Distance in px from the side edge. Ignored by the edge-tab shape."
        },
        "offsetY": {
          "type": "number",
          "minimum": 0,
          "maximum": 200,
          "default": 20,
          "description": "Distance in px from the top or bottom edge. For middle it shifts the button down from the center; for upper and lower it is the margin kept at the top and bottom of the screen."
        },
        "size": {
          "type": "number",
          "minimum": 44,
          "maximum": 96,
          "default": 56,
          "description": "Button height in px."
        },
        "shape": {
          "enum": [
            "circle",
            "rounded",
            "pill",
            "edge-tab"
          ],
          "default": "circle"
        },
        "background": {
          "type": "string",
          "description": "CSS color. Default: theme.primary."
        },
        "foreground": {
          "type": "string",
          "description": "CSS color for the symbol and label. Default: black or white, whichever contrasts more. Replaced automatically if below 4.5:1 contrast."
        },
        "labelText": {
          "type": "string",
          "maxLength": 40,
          "description": "Custom visible label for the pill and edge-tab shapes. Default: the word for accessibility in the panel language."
        },
        "labelLanguage": {
          "enum": [
            "he",
            "ar",
            "ru",
            "en"
          ],
          "description": "Fix the built-in label's language instead of following the panel language."
        },
        "mobile": {
          "type": "object",
          "additionalProperties": false,
          "description": "Overrides for screens up to 640px wide.",
          "properties": {
            "position": {
              "enum": [
                "top-right",
                "top-left",
                "upper-right",
                "upper-left",
                "middle-right",
                "middle-left",
                "lower-right",
                "lower-left",
                "bottom-right",
                "bottom-left"
              ]
            },
            "offsetX": {
              "type": "number",
              "minimum": 0,
              "maximum": 200
            },
            "offsetY": {
              "type": "number",
              "minimum": 0,
              "maximum": 200
            },
            "size": {
              "type": "number",
              "minimum": 44,
              "maximum": 96
            }
          }
        },
        "draggable": {
          "type": "boolean",
          "default": true,
          "description": "Visitors can drag the button to one of the ten positions, or choose one in the panel's button position card. Their choice is saved only in their own browser and Reset settings removes it. false keeps the button where you put it and hides the card."
        }
      }
    },
    "theme": {
      "type": "object",
      "additionalProperties": false,
      "description": "Panel colors (any CSS color). Text colors that fall below 4.5:1 contrast are replaced with black or white automatically and a warning is logged.",
      "properties": {
        "primary": {
          "type": "string",
          "description": "Header, selected tiles and tile icons. Default #1f5eff."
        },
        "onPrimary": {
          "type": "string",
          "description": "Text and icons on the primary color. Default: black or white, whichever contrasts more."
        },
        "background": {
          "type": "string",
          "description": "Panel background. Default #ffffff."
        },
        "text": {
          "type": "string",
          "description": "Panel text. Default #1d1d1f."
        },
        "muted": {
          "type": "string",
          "description": "Secondary text. Default #5f6672."
        },
        "border": {
          "type": "string",
          "description": "Tile and divider borders. Default #d5dbe7."
        },
        "surface": {
          "type": "string",
          "description": "Subtle highlight backgrounds. Default #f3f6ff."
        },
        "scrollbar": {
          "type": "string",
          "description": "Scrollbar thumb inside the panel and the statement window. Default: theme.primary. Below 3:1 against theme.surface (WCAG 1.4.11) it is replaced with theme.text, with a warning."
        }
      }
    },
    "statement": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "organizationName": {
          "$ref": "#/$defs/ownerText",
          "description": "Legal or public name of the organization. Required for a complete statement."
        },
        "organizationDescription": {
          "$ref": "#/$defs/ownerText",
          "description": "One line describing the organization or the site."
        },
        "commitment": {
          "$ref": "#/$defs/ownerText",
          "description": "Your commitment to accessibility, in your own words."
        },
        "updatedAt": {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
          "description": "Date the statement was last reviewed, as YYYY-MM-DD. Required for a complete statement."
        },
        "conformanceLevel": {
          "enum": [
            "A",
            "AA",
            "AAA"
          ],
          "description": "Only set a level your site was actually audited at; the statement never claims a level you did not set."
        },
        "additionalStandards": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ownerText"
          },
          "description": "Other standards the site was checked against, for example WCAG 2.2 AA."
        },
        "adjustments": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ownerText"
          },
          "description": "Accessibility adjustments the site offers. Required for a complete statement."
        },
        "reviewFrequency": {
          "$ref": "#/$defs/ownerText",
          "description": "How often accessibility is reviewed, for example every 6 months."
        },
        "measures": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ownerText"
          },
          "description": "Measures taken to keep the site accessible, such as audits or staff training."
        },
        "browsers": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ownerText"
          },
          "description": "Browsers the site was tested with."
        },
        "assistiveTech": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ownerText"
          },
          "description": "Assistive technologies the site was tested with."
        },
        "knownLimitations": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ownerText"
          },
          "description": "Known parts of the site that are not accessible."
        },
        "thirdPartyPages": {
          "type": "array",
          "description": "Pages or content provided by third parties that you do not control.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "url": {
                "type": "string",
                "description": "http(s) or relative URL of the page."
              },
              "description": {
                "$ref": "#/$defs/ownerText",
                "description": "What the page is."
              }
            },
            "required": [
              "url"
            ]
          }
        },
        "exemptions": {
          "type": "array",
          "description": "Parts of the site for which you rely on a legal exemption.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "scope": {
                "$ref": "#/$defs/ownerText",
                "description": "What the exemption covers."
              },
              "type": {
                "enum": [
                  "financial",
                  "technological",
                  "other"
                ],
                "description": "Kind of exemption."
              },
              "expires": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "description": "Date the exemption ends, as YYYY-MM-DD."
              },
              "alternatives": {
                "$ref": "#/$defs/ownerText",
                "description": "How visitors can get the same service another way. Required for a technological exemption (regulation 35ו(ג))."
              }
            },
            "required": [
              "scope",
              "type"
            ]
          }
        },
        "stage": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "description": {
              "$ref": "#/$defs/ownerText",
              "description": "Current stage of the accessibility work."
            },
            "completionDate": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "description": "Planned completion date, as YYYY-MM-DD."
            },
            "alternatives": {
              "$ref": "#/$defs/ownerText",
              "description": "Alternatives available until the work is done."
            }
          },
          "description": "Use when the site is still being made accessible.",
          "required": [
            "description"
          ]
        },
        "temporaryNotices": {
          "type": "array",
          "description": "Short-lived notices, such as a page that is being fixed.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "text": {
                "$ref": "#/$defs/ownerText",
                "description": "The notice."
              },
              "until": {
                "type": "string",
                "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
                "description": "Date the notice stops applying, as YYYY-MM-DD."
              }
            },
            "required": [
              "text"
            ]
          }
        },
        "physicalArrangements": {
          "$ref": "#/$defs/ownerText",
          "description": "Accessibility arrangements at the physical premises. Required unless noPhysicalService is true."
        },
        "noPhysicalService": {
          "type": "boolean",
          "description": "Set true when the organization has no physical place that serves the public."
        },
        "coordinator": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "name": {
              "$ref": "#/$defs/ownerText",
              "description": "Contact person's name."
            },
            "phone": {
              "type": "string",
              "description": "Phone number, digits with optional + ( ) - and spaces."
            },
            "email": {
              "type": "string",
              "description": "Email address."
            },
            "other": {
              "$ref": "#/$defs/ownerText",
              "description": "Any other way to reach them, such as a fax number or postal address."
            }
          },
          "description": "The accessibility coordinator. Either coordinator or contact is required."
        },
        "contact": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "name": {
              "$ref": "#/$defs/ownerText",
              "description": "Contact person's name."
            },
            "phone": {
              "type": "string",
              "description": "Phone number, digits with optional + ( ) - and spaces."
            },
            "email": {
              "type": "string",
              "description": "Email address."
            },
            "other": {
              "$ref": "#/$defs/ownerText",
              "description": "Any other way to reach them, such as a fax number or postal address."
            }
          },
          "description": "A general accessibility contact. Either coordinator or contact is required."
        }
      },
      "description": "Data for the generated accessibility statement. Missing required items are listed on the statement page instead of being invented."
    }
  },
  "$defs": {
    "ownerText": {
      "description": "Text you write: one string, shown as written in every language the statement appears in, or one value per language. The statement shows the value in its own language, else the value in the page's language, else the first value given.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "object",
          "additionalProperties": false,
          "minProperties": 1,
          "properties": {
            "he": {
              "type": "string"
            },
            "ar": {
              "type": "string"
            },
            "ru": {
              "type": "string"
            },
            "en": {
              "type": "string"
            }
          }
        }
      ]
    }
  }
}
